/// <summary> /// Unlock a specific door within an SRim file. /// </summary> /// <param name="paths">KPaths object for this game.</param> /// <param name="area">Name of the SRim file to modify.</param> /// <param name="label">Label of the door to unlock.</param> private static void UnlockDoorInFile(KPaths paths, string area, string label) { var areaFiles = paths.FilesInModules.Where(fi => fi.Name.Contains(LookupTable[area])); foreach (FileInfo fi in areaFiles) { // Skip any files that don't end in "s.rim". if (fi.Name[fi.Name.Length - 5] != 's') { continue; } RIM r = new RIM(fi.FullName); // Open what replaced this area. RIM.rFile rf = r.File_Table.FirstOrDefault(x => x.Label == label); GFF g = new GFF(rf.File_Data); // Grab the door out of the file. // Set fields related to opening and unlocking. (g.Top_Level.Fields.FirstOrDefault(x => x.Label == "KeyRequired") as GFF.BYTE).Value = 0; (g.Top_Level.Fields.FirstOrDefault(x => x.Label == "Locked") as GFF.BYTE).Value = 0; (g.Top_Level.Fields.FirstOrDefault(x => x.Label == "OpenLockDC") as GFF.BYTE).Value = 0; (g.Top_Level.Fields.FirstOrDefault(x => x.Label == "Plot") as GFF.BYTE).Value = 0; // Set fields related to bashing open. (g.Top_Level.Fields.FirstOrDefault(x => x.Label == "Hardness") as GFF.BYTE).Value = 0; (g.Top_Level.Fields.FirstOrDefault(x => x.Label == "HP") as GFF.SHORT).Value = 1; (g.Top_Level.Fields.FirstOrDefault(x => x.Label == "CurrentHP") as GFF.SHORT).Value = 1; (g.Top_Level.Fields.FirstOrDefault(x => x.Label == "Min1HP") as GFF.BYTE).Value = 0; // Write change(s) to file. rf.File_Data = g.ToRawData(); r.WriteToFile(fi.FullName); } }
public void MeshLoads() { Settings.initializeSettings(); String meshERFPath = "E:\\Program Files (x86)\\Steam\\steamapps\\common\\dragon age origins\\packages\\core\\data\\modelmeshdata.erf"; ERF meshes = new ERF(meshERFPath); meshes.readKeyData(); Assert.Greater(meshes.resourceCount, 0); int failures = 0; for (int i = 0; i < meshes.resourceCount; i++) { GFF temp = IO.findFile <GFF>(meshes.resourceNames[i]); Assert.NotNull(temp, "Not found: |" + meshes.resourceNames[i] + "|" + i); if (Path.GetExtension(meshes.resourceNames[i]) == ".msh") { try { ModelMesh tempH = new ModelMesh(temp); } catch (Exception) { Console.WriteLine(meshes.resourceNames[i]); failures++; } } } Assert.AreEqual(0, failures); }
/// <summary> /// Update warp coordinates that are in bad locations by default. /// </summary> /// <param name="paths">KPaths object for this game.</param> private static void FixWarpCoordinates(KPaths paths) { // Create a lookup for modules needing coordinate fix with their newly shuffled FileInfos. var shuffleFileLookup = new Dictionary <string, FileInfo>(); foreach (var key in Globals.FIXED_COORDINATES.Keys) { shuffleFileLookup.Add(key, paths.FilesInModules.FirstOrDefault(fi => fi.Name.Contains(LookupTable[key]))); } foreach (var kvp in shuffleFileLookup) { // Set up objects. RIM r = new RIM(kvp.Value.FullName); RIM.rFile rf = r.File_Table.FirstOrDefault(x => x.TypeID == (int)ResourceType.IFO); GFF g = new GFF(rf.File_Data); // Update coordinate data. (g.Top_Level.Fields.FirstOrDefault(x => x.Label == Properties.Resources.ModuleEntryX) as GFF.FLOAT).Value = Globals.FIXED_COORDINATES[kvp.Key].Item1; (g.Top_Level.Fields.FirstOrDefault(x => x.Label == Properties.Resources.ModuleEntryY) as GFF.FLOAT).Value = Globals.FIXED_COORDINATES[kvp.Key].Item2; (g.Top_Level.Fields.FirstOrDefault(x => x.Label == Properties.Resources.ModuleEntryZ) as GFF.FLOAT).Value = Globals.FIXED_COORDINATES[kvp.Key].Item3; // Write updated data to RIM file. rf.File_Data = g.ToRawData(); r.WriteToFile(kvp.Value.FullName); } }
//Processes the next job private void proccessJobs() { toggleButtons(false); while (jobs.Count > 0) { Settings.stream.WriteLine(); String currentJob = jobs.Dequeue(); Settings.stream.WriteLine("Starting next job ({0}):", currentJob); String extention = Path.GetExtension(currentJob); if (extention == ".gff" || extention == ".msh" || extention == ".mmh" || extention == ".tmsh") { GFF file = ResourceManager.findFile <GFF>(currentJob); if (file != null) { Settings.stream.WriteLine("This is a GFF file, printing struct definitions:"); Settings.stream.WriteText(ResourceManager.getGFFLayout(file)); } else { Settings.stream.WriteLine("Couldn't find {0}, skipping this job.", currentJob); } } else { //Run lightmapping! try { Scene currentScene; Settings.stream.WriteText("Loading . . . "); Stopwatch watch = Stopwatch.StartNew(); switch (Path.GetExtension(currentJob)) { case ".xml": currentScene = new XMLScene(currentJob); break; case ".lvl": currentScene = new LevelScene(currentJob); break; default: throw new LightmappingAbortedException("The scene \"" + currentJob + "\" is not a valid file format. Valid file formats are .xml and .lvl."); } watch.Stop(); Settings.stream.WriteLine("Done ({0}ms)", watch.ElapsedMilliseconds); List <LightMap> maps = Lightmapper.runLightmaps(currentScene.lightmapModels, currentScene.lights); currentScene.exportLightmaps(maps); } catch (LightmappingAbortedException e) { Settings.stream.WriteLine("Error: " + e.Message); } } } Settings.stream.WriteLine("Finished all jobs."); toggleButtons(true); }
public void SettingsERFNotNull() { Settings.initializeSettings(); foreach (ERF e in Settings.erfFiles) { Assert.NotNull(e); Console.WriteLine(e.path); for (int i = 0; i < e.resourceCount; i++) { GFF temp = IO.findFile <GFF>(e.resourceNames[i]); Assert.NotNull(temp); } } }
//Returns a string describing the struct definitions of the GFF file public static String getGFFLayout(GFF file) { StringBuilder layout = new StringBuilder(); for (int i = 0; i < file.structs.Length; i++) { layout.AppendFormat("{0}. {1}{2}", i, file.structs[i].definition.ToString(), Environment.NewLine); for (int j = 0; j < file.structs[i].fields.Length; j++) { layout.AppendFormat("\t{0}. {1}{2}", j, file.structs[i].fields[j].ToString(), Environment.NewLine); } } return(layout.ToString()); }
private void readScene(String path) { BinaryReader sceneReader = new BinaryReader(new FileStream(path + "\\job_scene.xml", FileMode.Open, FileAccess.Read, FileShare.Read)); String sceneXML = Encoding.UTF8.GetString(sceneReader.ReadBytes((int)sceneReader.BaseStream.Length)); sceneReader.Close(); XmlDocument sceneSpecification = new XmlDocument(); sceneSpecification.LoadXml(sceneXML); XmlNode scene = sceneSpecification.SelectSingleNode("RenderFarmScene"); foreach (XmlNode model in scene.ChildNodes) { String modelName = model.Attributes.GetNamedItem("Source").Value; String pathName = Path.GetDirectoryName(modelName); String filename = Path.GetFileName(modelName).ToLower(); modelName = pathName + "\\" + filename; ResourceManager.addFilePath(pathName); if (Path.GetFileName(modelName) == "prp_fertblsm_01.mmh") { continue; } GFF hierarchy = ResourceManager.findFile <GFF>(modelName); ModelHierarchy modelHierarchy = new ModelHierarchy(hierarchy); Model modelMesh = modelHierarchy.mesh.toModel(); foreach (XmlNode instance in model.ChildNodes) { String instanceName = instance.Attributes.GetNamedItem("Name").Value; Matrix4 transform = xmlToMatrix(instance.SelectSingleNode("Transform").Attributes); modelDictionary.Add(instanceName, new ModelInstance(instanceName, modelMesh, transform)); } ResourceManager.removeFilePath(pathName); } }
private void modelListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (modelListBox.SelectedItem != null) { String itemName = (String)modelListBox.SelectedItem; if (Path.GetExtension(itemName) == ".msh") { GFF tempGFF = ResourceManager.findFile <GFF>(itemName); if (tempGFF != null) { renderer.clearOverlays(); renderer.overlayText(tempGFF.path); renderer.showOverlays(); renderer.displayModel(new ModelMesh(tempGFF)); } else { Console.WriteLine("Couldn't find {0}", itemName); } } else if (Path.GetExtension(itemName) == ".mmh") { GFF tempGFF = ResourceManager.findFile <GFF>(itemName); if (tempGFF != null) { ModelHierarchy mh = new ModelHierarchy(tempGFF); if (mh.loadedMesh) { renderer.clearOverlays(); renderer.overlayText(mh.mmhName); renderer.showOverlays(); renderer.displayModel(mh.mesh); } else { Console.WriteLine("Couldn't load mesh {0} for {1}", mh.mshName, mh.mmhName); } } else { Console.WriteLine("Couldn't find {0}", itemName); } } else if (Path.GetExtension(itemName) == ".dds") { try { DDS texture = ResourceManager.findFile <DDS>(itemName); if (texture != null) { renderer.displayDDS(texture); } else { Console.WriteLine("Couldn't find {0}", itemName); } } catch (NotImplementedException ex) { Console.WriteLine(ex.Message); } } else if (Path.GetExtension(itemName) == ".mao") { MaterialObject mao = ResourceManager.findFile <MaterialObject>(itemName); } } }
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); } }
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(); }
// Populates and shuffles the the modules flagged to be randomized. Returns true if override files should be added. public static void Module_rando(KPaths paths) { // Set up the bound module collection if it hasn't been already. if (!Properties.Settings.Default.ModulesInitialized) { Globals.BoundModules.Clear(); foreach (string s in Globals.MODULES) { Globals.BoundModules.Add(new Globals.Mod_Entry(s, true)); } Properties.Settings.Default.ModulesInitialized = true; } //if (!Properties.Settings.Default.ModulePresetSelected) //{ // //Figure something out here //} // Split the Bound modules into their respective lists. List <string> ExcludedModules = Globals.BoundModules.Where(x => x.Omitted).Select(x => x.Name).ToList(); List <string> IncludedModules = Globals.BoundModules.Where(x => !x.Omitted).Select(x => x.Name).ToList(); // Shuffle the list of included modules. List <string> ShuffledModules = IncludedModules.ToList(); Randomize.FisherYatesShuffle(ShuffledModules); // Copy shuffled modules into the base directory. Dictionary <string, string> LookupTable = new Dictionary <string, string>(); // Create lookup table to find a given module's new "name". for (int i = 0; i < IncludedModules.Count; i++) { LookupTable.Add(IncludedModules[i], ShuffledModules[i]); File.Copy($"{paths.modules_backup}{IncludedModules[i]}.rim", $"{paths.modules}{ShuffledModules[i]}.rim", true); File.Copy($"{paths.modules_backup}{IncludedModules[i]}_s.rim", $"{paths.modules}{ShuffledModules[i]}_s.rim", true); File.Copy($"{paths.lips_backup}{IncludedModules[i]}_loc.mod", $"{paths.lips}{ShuffledModules[i]}_loc.mod", true); } // Copy excluded, untouched modules into the base directory. foreach (string name in ExcludedModules) { LookupTable.Add(name, name); File.Copy($"{paths.modules_backup}{name}.rim", $"{paths.modules}{name}.rim", true); File.Copy($"{paths.modules_backup}{name}_s.rim", $"{paths.modules}{name}_s.rim", true); File.Copy($"{paths.lips_backup}{name}_loc.mod", $"{paths.lips}{name}_loc.mod", true); } // Copy lips extras into the base directory. foreach (string name in Globals.lipXtras) { File.Copy($"{paths.lips_backup}{name}", $"{paths.lips}{name}", true); } // Write additional override files. string moduleSavePath = Path.Combine(paths.Override, TwoDA_MODULE_SAVE); ModuleExtras saveFileExtras = Properties.Settings.Default.ModuleExtrasValue & (ModuleExtras.SaveAllModules | ModuleExtras.SaveMiniGames | ModuleExtras.NoSaveDelete); //if (0 == (saveFileExtras ^ (ModuleExtras.Default))) //{ // // 0b000 - Milestone Delete (Default) // // Do nothing. //} if (0 == (saveFileExtras ^ (ModuleExtras.NoSaveDelete))) { // 0b001 - No Milestone Delete File.WriteAllBytes(moduleSavePath, Properties.Resources.NODELETE_modulesave); } if (0 == (saveFileExtras ^ (ModuleExtras.SaveMiniGames))) { // 0b010 - Include Minigames | Milestone Delete File.WriteAllBytes(moduleSavePath, Properties.Resources.MGINCLUDED_modulesave); } if (0 == (saveFileExtras ^ (ModuleExtras.NoSaveDelete | ModuleExtras.SaveMiniGames))) { // 0b011 - Include Minigames | No Milestone Delete File.WriteAllBytes(moduleSavePath, Properties.Resources.NODELETE_MGINCLUDED_modulesave); } if (0 == (saveFileExtras ^ (ModuleExtras.SaveAllModules)) || 0 == (saveFileExtras ^ (ModuleExtras.SaveMiniGames | ModuleExtras.SaveAllModules))) { // Treat both the same. // 0b100 - Include All Modules | Milestone Delete // 0b110 - Include All Modules | Include Minigames | Milestone Delete File.WriteAllBytes(moduleSavePath, Properties.Resources.ALLINCLUDED_modulesave); } if (0 == (saveFileExtras ^ (ModuleExtras.NoSaveDelete | ModuleExtras.SaveAllModules)) || 0 == (saveFileExtras ^ (ModuleExtras.NoSaveDelete | ModuleExtras.SaveMiniGames | ModuleExtras.SaveAllModules))) { // Treat both the same. // 0b101 - Include All Modules | No Milestone Delete // 0b111 - Include All Modules | Include Minigames | No Milestone Delete File.WriteAllBytes(moduleSavePath, Properties.Resources.NODELETE_ALLINCLUDED_modulesave); } if (Properties.Settings.Default.ModuleExtrasValue.HasFlag(ModuleExtras.FixDream)) { File.WriteAllBytes(Path.Combine(paths.Override, FIXED_DREAM_OVERRIDE), Properties.Resources.k_ren_visionland); } if (Properties.Settings.Default.ModuleExtrasValue.HasFlag(ModuleExtras.UnlockGalaxyMap)) { File.WriteAllBytes(Path.Combine(paths.Override, UNLOCK_MAP_OVERRIDE), Properties.Resources.k_pebn_galaxy); } // Fix warp coordinates. if (Properties.Settings.Default.ModuleExtrasValue.HasFlag(ModuleExtras.FixCoordinates)) { // Create a lookup for modules needing coordinate fix with their newly shuffled FileInfos. var shuffleFileLookup = new Dictionary <string, FileInfo>(); foreach (var key in Globals.FIXED_COORDINATES.Keys) { shuffleFileLookup.Add(key, paths.FilesInModules.FirstOrDefault(fi => fi.Name.Contains(LookupTable[key]))); } foreach (var kvp in shuffleFileLookup) { // Set up objects. RIM r = new RIM(kvp.Value.FullName); RIM.rFile rf = r.File_Table.Where(x => x.TypeID == (int)ResourceType.IFO).FirstOrDefault(); GFF g = new GFF(rf.File_Data); // Update coordinate data. g.Field_Array.Where(x => x.Label == Properties.Resources.ModuleEntryX).FirstOrDefault().DataOrDataOffset = Globals.FIXED_COORDINATES[kvp.Key].Item1; g.Field_Array.Where(x => x.Label == Properties.Resources.ModuleEntryY).FirstOrDefault().DataOrDataOffset = Globals.FIXED_COORDINATES[kvp.Key].Item2; g.Field_Array.Where(x => x.Label == Properties.Resources.ModuleEntryZ).FirstOrDefault().DataOrDataOffset = Globals.FIXED_COORDINATES[kvp.Key].Item3; // Write updated data to RIM file. rf.File_Data = g.ToRawData(); r.WriteToFile(kvp.Value.FullName); } } // Fixed Rakata riddle Man in Mind Prison. if (Properties.Settings.Default.ModuleExtrasValue.HasFlag(ModuleExtras.FixMindPrison)) { // Find the files associated with AREA_MYSTERY_BOX. var files = paths.FilesInModules.Where(fi => fi.Name.Contains(LookupTable[AREA_MYSTERY_BOX])); foreach (FileInfo fi in files) { // Skip any files that don't end in "s.rim". if (fi.Name[fi.Name.Length - 5] != 's') { continue; } // Check the RIM's File_Table for any rFiles labeled with LABEL_MIND_PRISON. RIM r = new RIM(fi.FullName); if (r.File_Table.Where(x => x.Label == LABEL_MIND_PRISON).Any()) { bool offadjust = false; foreach (RIM.rFile rf in r.File_Table) { // For the rFile with LABEL_MIND_PRISON, update the file data with the fix. if (rf.Label == LABEL_MIND_PRISON) { rf.File_Data = Properties.Resources.g_brakatan003; rf.DataSize += 192; offadjust = true; continue; } // For rFiles after LABEL_MIND_PRISON, add the additional data offset. if (offadjust) { rf.DataOffset += 192; } } // Write updated RIM data to file. r.WriteToFile(fi.FullName); } } } }
//Randomize Dialogue static void shuffle_dialogue(KPaths paths, bool Entries, bool Replies, bool SoundMatching) { TLK t = new TLK(paths.dialog); foreach (FileInfo fi in paths.FilesInModules) { if (fi.Name[fi.Name.Length - 5] != 's') { continue; } RIM r = new RIM(fi.FullName); foreach (RIM.rFile RF in r.File_Table.Where(x => x.TypeID == (int)ResourceType.DLG)) { GFF g = new GFF(RF.File_Data); //Entries if (Entries) { foreach (GFF.STRUCT S in (g.Top_Level.Fields.Where(x => x.Label == "EntryList").FirstOrDefault() as GFF.LIST).Structs) { if ((S.Fields.Where(x => x.Label == "Text").FirstOrDefault() as GFF.CExoLocString).StringRef != -1) // Avoid overwriting dialogue end indicators, and animation nodes { int str_ref = 0; // Find valid string while (t.String_Data_Table[str_ref].SoundResRef == "" || t.String_Data_Table[str_ref].SoundResRef[0] == '_' || t.String_Data_Table[str_ref].SoundResRef.ToLower().Contains("comp")) //Ensure the string we have has a sound to go with it, starting with undescord means it's player dialogue, which doesn't have audio in this game { str_ref = Randomize.Rng.Next(TLK_STRING_COUNT); } if (!EntriesLookupTable.ContainsKey(fi.Name)) { EntriesLookupTable.Add(fi.Name, new Dictionary <string, List <Tuple <int, int, string, string, string, string> > >()); } if (!EntriesLookupTable[fi.Name].ContainsKey(RF.Label)) { EntriesLookupTable[fi.Name].Add(RF.Label, new List <Tuple <int, int, string, string, string, string> >()); } // Sound and Text Matching if (SoundMatching) { var text = S.Fields.Where(x => x.Label == "Text").FirstOrDefault() as GFF.CExoLocString; int textOrig = text.StringRef; int textRand = str_ref; text.StringRef = str_ref; string VORefOrig = ""; string VORefRand = ""; string SoundOrig = ""; string SoundRand = ""; try { var voResRef = S.Fields.Where(x => x.Label == "VO_ResRef").FirstOrDefault() as GFF.ResRef; VORefOrig = voResRef.Reference; VORefRand = t.String_Data_Table[str_ref].SoundResRef; voResRef.Reference = VORefRand; } catch { VORefOrig = ""; VORefRand = ""; } try { var sound = S.Fields.Where(x => x.Label == "Sound").FirstOrDefault() as GFF.ResRef; SoundOrig = sound.Reference; SoundRand = t.String_Data_Table[str_ref].SoundResRef; sound.Reference = SoundRand; } catch { SoundOrig = ""; SoundRand = ""; } // If both VO_ResRef and Sound Fail we ignore the entry EntriesLookupTable[fi.Name][RF.Label].Add(new Tuple <int, int, string, string, string, string>(textOrig, textRand, VORefOrig, VORefRand, SoundOrig, SoundRand)); } else { var text = S.Fields.Where(x => x.Label == "Text").FirstOrDefault() as GFF.CExoLocString; EntriesLookupTable[fi.Name][RF.Label].Add(new Tuple <int, int, string, string, string, string>(text.StringRef, str_ref, "", "", "", "")); text.StringRef = str_ref; } } } } //Replies if (Replies) { foreach (GFF.STRUCT S in (g.Top_Level.Fields.Where(x => x.Label == "ReplyList").FirstOrDefault() as GFF.LIST).Structs) { if ((S.Fields.Where(x => x.Label == "Text").FirstOrDefault() as GFF.CExoLocString).StringRef != -1) //Avoid overwriting dialogue end indicators, and animation nodes { if (!RepliesLookupTable.ContainsKey(fi.Name)) { RepliesLookupTable.Add(fi.Name, new Dictionary <string, List <Tuple <int, int> > >()); } if (!RepliesLookupTable[fi.Name].ContainsKey(RF.Label)) { RepliesLookupTable[fi.Name].Add(RF.Label, new List <Tuple <int, int> >()); } int str_ref = Randomize.Rng.Next(TLK_STRING_COUNT); while (t.String_Data_Table[str_ref].StringText == "") { str_ref = Randomize.Rng.Next(TLK_STRING_COUNT); } var text = S.Fields.Where(x => x.Label == "Text").FirstOrDefault() as GFF.CExoLocString; RepliesLookupTable[fi.Name][RF.Label].Add(new Tuple <int, int>(text.StringRef, str_ref)); text.StringRef = str_ref; } } } Array.Clear(RF.File_Data, 0, RF.File_Data.Length); RF.File_Data = g.ToRawData(); } r.WriteToFile(fi.FullName); } }
public static void model_rando(KPaths paths) { foreach (FileInfo fi in paths.FilesInModules) { RIM r = new RIM(fi.FullName); // Doors if ((Properties.Settings.Default.RandomizeDoorModels & 1) > 0) { foreach (RIM.rFile rf in r.File_Table.Where(x => x.TypeID == (int)ResourceType.UTD)) { GFF g = new GFF(rf.File_Data); int temp = 0; if ((Properties.Settings.Default.RandomizeDoorModels & 4) > 0) // Broken Doors { temp = Randomize.Rng.Next(13, 64); // First 12 doors are open so this is easier } else { temp = Randomize.Rng.Next(0, 64); } // Airlock if ((Properties.Settings.Default.RandomizeDoorModels & 2) > 0 && (g.Field_Array.Where(x => x.Label == "LocName").FirstOrDefault().Field_Data as GFF.CExoLocString).StringRef == 21080) { continue; } g.Field_Array.Where(k => k.Label == "GenericType").FirstOrDefault().Field_Data = temp; g.Field_Array.Where(k => k.Label == "GenericType").FirstOrDefault().DataOrDataOffset = temp; MemoryStream ms = new MemoryStream(); rf.File_Data = g.ToRawData(); } } //Placeables if ((Properties.Settings.Default.RandomizePlaceModels & 1) > 0) { foreach (RIM.rFile rf in r.File_Table.Where(k => k.TypeID == 2044)) { GFF g = new GFF(rf.File_Data); int temp = Randomize.Rng.Next(0, 231); bool broken_satisfied = !((Properties.Settings.Default.RandomizePlaceModels & 4) > 0) || !Globals.BROKEN_PLACE.Contains(temp); //Always Satisfied if Broken omission disbaled bool large_satisfied = !((Properties.Settings.Default.RandomizePlaceModels & 2) > 0) || !Globals.LARGE_PLACE.Contains(temp); //Always satisifed if Large omission disabled while (!(broken_satisfied && large_satisfied)) { temp = Randomize.Rng.Next(0, 231); broken_satisfied = !((Properties.Settings.Default.RandomizePlaceModels & 4) > 0) || !Globals.BROKEN_PLACE.Contains(temp); //Always Satisfied if Broken omission disbaled large_satisfied = !((Properties.Settings.Default.RandomizePlaceModels & 2) > 0) || !Globals.LARGE_PLACE.Contains(temp); //Always satisifed if Large omission disabled } g.Field_Array.Where(k => k.Label == "Appearance").FirstOrDefault().Field_Data = temp; g.Field_Array.Where(k => k.Label == "Appearance").FirstOrDefault().DataOrDataOffset = temp; MemoryStream ms = new MemoryStream(); rf.File_Data = g.ToRawData(); } } //Characters if ((Properties.Settings.Default.RandomizeCharModels & 1) > 0) { foreach (RIM.rFile rf in r.File_Table.Where(k => k.TypeID == 2027)) { GFF g = new GFF(rf.File_Data); int temp = Randomize.Rng.Next(0, 508); bool broken_satisfied = !((Properties.Settings.Default.RandomizeCharModels & 4) > 0) || !Globals.BROKEN_CHARS.Contains(temp); //Always Satisfied if Broken omission disbaled bool large_satisfied = !((Properties.Settings.Default.RandomizeCharModels & 2) > 0) || !Globals.LARGE_CHARS.Contains(temp); //Always satisifed if Large omission disabled while (!(broken_satisfied && large_satisfied)) { temp = Randomize.Rng.Next(0, 508); broken_satisfied = !((Properties.Settings.Default.RandomizeCharModels & 4) > 0) || !Globals.BROKEN_CHARS.Contains(temp); //Always Satisfied if Broken omission disbaled large_satisfied = !((Properties.Settings.Default.RandomizeCharModels & 2) > 0) || !Globals.LARGE_CHARS.Contains(temp); //Always satisifed if Large omission disabled } g.Field_Array.Where(k => k.Label == "Appearance_Type").FirstOrDefault().Field_Data = temp; g.Field_Array.Where(k => k.Label == "Appearance_Type").FirstOrDefault().DataOrDataOffset = temp; MemoryStream ms = new MemoryStream(); rf.File_Data = g.ToRawData(); } } r.WriteToFile(fi.FullName); } }
/// <summary> /// Unlock Leviathan Hangar option in the other two elevator access, and enables the use of the Hangar elevator. /// </summary> /// <param name="paths">KPaths object for this game.</param> private static void FixLeviathanElevators(KPaths paths) { var lev_files_a = paths.FilesInModules.Where(fi => fi.Name.Contains(LookupTable[AREA_LEV_PRISON])); var lev_files_b = paths.FilesInModules.Where(fi => fi.Name.Contains(LookupTable[AREA_LEV_COMMAND])); var lev_files_c = paths.FilesInModules.Where(fi => fi.Name.Contains(LookupTable[AREA_LEV_HANGAR])); // Prison Block Fix - Unlock option to visit Hangar. foreach (FileInfo fi in lev_files_a) { // Skip any files that don't end in "s.rim". if (fi.Name[fi.Name.Length - 5] != 's') { continue; } RIM r_lev = new RIM(fi.FullName); GFF g_lev = new GFF(r_lev.File_Table.FirstOrDefault(x => x.Label == LABEL_LEV_ELEVATOR_A).File_Data); // Change Entry connecting for bridge option Index to 3, which will transition to the command deck (((g_lev.Top_Level.Fields.FirstOrDefault(x => x.Label == "ReplyList") as GFF.LIST).Structs.FirstOrDefault(x => x.Struct_Type == 3).Fields.FirstOrDefault(x => x.Label == "EntriesList") as GFF.LIST).Structs.FirstOrDefault(x => x.Struct_Type == 0).Fields.FirstOrDefault(x => x.Label == "Index") as GFF.DWORD).Value = 3; // Sets the active reference for the hangar option to nothing, meaning there is no requirement to transition to the hangar (((g_lev.Top_Level.Fields.FirstOrDefault(x => x.Label == "ReplyList") as GFF.LIST).Structs.FirstOrDefault(x => x.Struct_Type == 1).Fields.FirstOrDefault(x => x.Label == "EntriesList") as GFF.LIST).Structs.FirstOrDefault(x => x.Struct_Type == 0).Fields.FirstOrDefault(x => x.Label == "Active") as GFF.ResRef).Reference = ""; r_lev.File_Table.FirstOrDefault(x => x.Label == LABEL_LEV_ELEVATOR_A).File_Data = g_lev.ToRawData(); r_lev.WriteToFile(fi.FullName); } // Command Deck Fix - Unlock option to visit Hangar. foreach (FileInfo fi in lev_files_b) { // Skip any files that don't end in "s.rim". if (fi.Name[fi.Name.Length - 5] != 's') { continue; } RIM r_lev = new RIM(fi.FullName); GFF g_lev = new GFF(r_lev.File_Table.FirstOrDefault(x => x.Label == LABEL_LEV_ELEVATOR_B).File_Data); // Sets the active reference for the hangar option to nothing, meaning there is no requirement to transition to the hangar (((g_lev.Top_Level.Fields.FirstOrDefault(x => x.Label == "ReplyList") as GFF.LIST).Structs.FirstOrDefault(x => x.Struct_Type == 1).Fields.FirstOrDefault(x => x.Label == "EntriesList") as GFF.LIST).Structs.FirstOrDefault(x => x.Struct_Type == 1).Fields.FirstOrDefault(x => x.Label == "Active") as GFF.ResRef).Reference = ""; r_lev.File_Table.FirstOrDefault(x => x.Label == LABEL_LEV_ELEVATOR_B).File_Data = g_lev.ToRawData(); r_lev.WriteToFile(fi.FullName); } // Hangar Fix - Enable the elevator so it can be used. foreach (FileInfo fi in lev_files_c) { // Skip any files that don't end in "s.rim". if (fi.Name[fi.Name.Length - 5] != 's') { continue; } RIM r_lev = new RIM(fi.FullName); // While I possess the ability to edit this file programmatically, due to the complexity I have opted to just load the modded file into resources. r_lev.File_Table.FirstOrDefault(x => x.Label == LABEL_LEV_ELEVATOR_C).File_Data = Properties.Resources.lev40_accntl_dlg; // Adding module transition scripts to RIM... // Prison Block r_lev.File_Table.Add(new RIM.rFile { TypeID = (int)ResourceType.NCS, Label = "k_plev_goto40aa", File_Data = Properties.Resources.k_plev_goto40aa }); // Command Deck r_lev.File_Table.Add(new RIM.rFile { TypeID = (int)ResourceType.NCS, Label = "k_plev_goto40ab", File_Data = Properties.Resources.k_plev_goto40ab }); r_lev.WriteToFile(fi.FullName); } }
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 BiowareStruct(GFF f, GFFStructDefinition def) { _binaryFile = f; _definition = def; }
private void btn_load_Click(object sender, EventArgs e) { setButtons(false); String filePath = tb_path.Text; file = filePath; String extention = Path.GetExtension(filePath); List <Mesh> renderableMeshes = new List <Mesh>(); drawString = "File: " + file; updateBitmap(drawString); //Try and find the model file if (extention == ".mmh") { GFF tempGFF = new GFF(filePath); ModelHierarchy mh = new ModelHierarchy(tempGFF); currentlyShowing = Showing.Model; meshes = mh.mesh.toModel().meshes; setButtons(true); if (meshes.Length > 0) { setMeshNum(0); } } else if (extention == ".msh") { GFF tempGFF = new GFF(filePath); ModelMesh mm = new ModelMesh(tempGFF); currentlyShowing = Showing.Model; meshes = mm.toModel().meshes; setButtons(true); if (meshes.Length > 0) { setMeshNum(0); } } else if (extention == ".tga") { texture = new Targa(filePath); currentlyShowing = Showing.Texture; } else if (extention == ".lvl") { level = new LevelScene(filePath); currentlyShowing = Showing.Level; List <Patch> patchList = new List <Patch>(); List <Triangle> tris = new List <Triangle>(); foreach (ModelInstance m in level.lightmapModels) { for (int i = 0; i < m.meshes.Length; i++) { if (m.meshes[i].isLightmapped) { //Make the lightmap LightMap temp = new LightMap(m, m.meshes[i]); //For each patch instance in the lightmap foreach (Patch p in temp.patches) { patchList.Add(p); } } } if (m.baseModel.castsShadows) { tris.AddRange(m.tris); } } octree = new Octree(tris); patches = patchList.ToArray(); } else if (extention == ".xml") { level = new XMLScene(filePath); currentlyShowing = Showing.Level; List <Patch> patchList = new List <Patch>(); List <Triangle> tris = new List <Triangle>(); foreach (ModelInstance m in level.lightmapModels) { for (int i = 0; i < m.meshes.Length; i++) { if (m.meshes[i].isLightmapped) { //Make the lightmap LightMap temp = new LightMap(m, m.meshes[i]); //For each patch instance in the lightmap foreach (Patch p in temp.patches) { patchList.Add(p); } } } if (m.baseModel.castsShadows) { tris.AddRange(m.tris); } } octree = new Octree(tris); patches = patchList.ToArray(); } //If its not the right type of file then print an error else { drawString = "This is not a valid model (.mmh or .msh), texture (.tga), level (.lvl), or scene (.xml) file!"; } refreshView(); }