コード例 #1
0
        /// <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);
            }
        }
コード例 #2
0
        /// <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);
            }
        }
コード例 #3
0
        /// <summary>
        /// Unlock the doors requested by the user.
        /// </summary>
        /// <param name="paths">KPaths object for this game.</param>
        private static void UnlockDoors(KPaths paths)
        {
            var extrasValue = Properties.Settings.Default.ModuleExtrasValue;

            // Dantooine Ruins
            if (extrasValue.HasFlag(ModuleExtras.UnlockDanRuins))
            {
                UnlockDoorInFile(paths, AREA_DAN_COURTYARD, LABEL_DANT_DOOR);
            }

            // Leviathan Elevators
            if (extrasValue.HasFlag(ModuleExtras.UnlockLevElev))
            {
                FixLeviathanElevators(paths);
            }

            // Manaan Embassy Door to Submersible
            if (extrasValue.HasFlag(ModuleExtras.UnlockManSub))
            {
                UnlockDoorInFile(paths, AREA_MAN_EAST_CENTRAL, LABEL_MAN_SUB_DOOR);
            }

            // Star Forge Door to Bastila
            if (extrasValue.HasFlag(ModuleExtras.UnlockStaBastila))
            {
                UnlockDoorInFile(paths, AREA_STA_DECK3, LABEL_STA_BAST_DOOR);
            }

            // Lehon Temple Roof
            if (extrasValue.HasFlag(ModuleExtras.UnlockUnkSummit))
            {
                UnlockDoorInFile(paths, AREA_UNK_SUMMIT, LABEL_UNK_DOOR);
            }
        }
コード例 #4
0
        /// <summary>
        /// Allow the Mystery Box and Mind Prison to be used more than once.
        /// </summary>
        /// <param name="paths">KPaths object for this game.</param>
        private static void FixMindPrison(KPaths paths)
        {
            // Allowing the Mystery Box to be accessed multiple times.
            ReplaceSRimFileData(paths, AREA_EBO_HAWK, LABEL_EBO_BOX, Properties.Resources.pebn_mystery);

            // Allowing Riddles to be done more than once.
            ReplaceSRimFileData(paths, AREA_EBO_BOX, LABEL_EBO_PRISON, Properties.Resources.g_brakatan003);
        }
コード例 #5
0
        /// <summary>
        /// Write special files to the override folder - save data, dream fix, galaxy map unlock, etc.
        /// </summary>
        /// <param name="paths">KPaths object for this game.</param>
        private static void WriteOverrideFiles(KPaths paths)
        {
            string       moduleSavePath = Path.Combine(paths.Override, TwoDA_MODULE_SAVE);
            ModuleExtras saveFileExtras = Properties.Settings.Default.ModuleExtrasValue & (ModuleExtras.SaveAllModules | ModuleExtras.SaveMiniGames | ModuleExtras.NoSaveDelete);

            // Save Data File
            switch ((int)saveFileExtras)
            {
            default:
                // 0b000 - Milestone Delete (Default)
                // Do nothing.
                break;

            case (int)(ModuleExtras.NoSaveDelete):
                // 0b001 - No Milestone Delete
                File.WriteAllBytes(moduleSavePath, Properties.Resources.NODELETE_modulesave);
                break;

            case (int)(ModuleExtras.SaveMiniGames):
                // 0b010 - Save Minigames | Milestone Delete
                File.WriteAllBytes(moduleSavePath, Properties.Resources.MGINCLUDED_modulesave);
                break;

            case (int)(ModuleExtras.NoSaveDelete | ModuleExtras.SaveMiniGames):
                // 0b011 - Save Minigames | No Milestone Delete
                File.WriteAllBytes(moduleSavePath, Properties.Resources.NODELETE_MGINCLUDED_modulesave);
                break;

            case (int)(ModuleExtras.SaveAllModules):
            case (int)(ModuleExtras.SaveMiniGames | ModuleExtras.SaveAllModules):
                // Treat both the same.
                // 0b100 - Save All Modules | Milestone Delete
                // 0b110 - Save All Modules | Save Minigames | Milestone Delete
                File.WriteAllBytes(moduleSavePath, Properties.Resources.ALLINCLUDED_modulesave);
                break;

            case (int)(ModuleExtras.NoSaveDelete | ModuleExtras.SaveAllModules):
            case (int)(ModuleExtras.NoSaveDelete | ModuleExtras.SaveMiniGames | ModuleExtras.SaveAllModules):
                // Treat both the same.
                // 0b101 - Save All Modules | No Milestone Delete
                // 0b111 - Save All Modules | Save Minigames | No Milestone Delete
                File.WriteAllBytes(moduleSavePath, Properties.Resources.NODELETE_ALLINCLUDED_modulesave);
                break;
            }

            // Fix Dream File
            if (Properties.Settings.Default.ModuleExtrasValue.HasFlag(ModuleExtras.FixDream))
            {
                File.WriteAllBytes(Path.Combine(paths.Override, FIXED_DREAM_OVERRIDE), Properties.Resources.k_ren_visionland);
            }

            // Unlock Galaxy Map File
            if (Properties.Settings.Default.ModuleExtrasValue.HasFlag(ModuleExtras.UnlockGalaxyMap))
            {
                File.WriteAllBytes(Path.Combine(paths.Override, UNLOCK_MAP_OVERRIDE), Properties.Resources.k_pebn_galaxy);
            }
        }
コード例 #6
0
        public static void text_rando(KPaths paths)
        {
            var settings = Properties.Settings.Default;

            if (settings.TextSettingsValue.HasFlag(TextSettings.RandoFullTLK)) //Shuffle TLK first, so sound matching still works
            {
                shuffle_TLK(paths, settings.TextSettingsValue.HasFlag(TextSettings.MatchSimLengthStrings));
            }
            if (settings.TextSettingsValue.HasFlag(TextSettings.RandoDialogEntries) || settings.TextSettingsValue.HasFlag(TextSettings.RandoDialogReplies))
            {
                shuffle_dialogue(paths, settings.TextSettingsValue.HasFlag(TextSettings.RandoDialogEntries), settings.TextSettingsValue.HasFlag(TextSettings.RandoDialogReplies), settings.TextSettingsValue.HasFlag(TextSettings.MatchEntrySoundsWText));
            }
        }
コード例 #7
0
        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.
            }
        }
コード例 #8
0
        //Randomize TLK
        static void shuffle_TLK(KPaths paths, bool LengthMatching)
        {
            TLK t = new TLK(paths.dialog);

            if (LengthMatching)
            {
                TLK t_ordered = new TLK(paths.dialog);

                t_ordered.String_Data_Table = t_ordered.String_Data_Table.OrderBy(x => x.StringText.Length).ToList();

                for (int i = 0; i < t.String_Data_Table.Count; i++)
                {
                    try
                    {
                        int index_offset = 0;
                        while (index_offset == 0)
                        {
                            index_offset = Randomize.Rng.Next(-5, 5);
                        }

                        // Could get faster execution time by matching the strings by lenght instead of text, but then there would be bias towards strings earlier in each lenght bracket.
                        var randomString = t_ordered.String_Data_Table[t_ordered.String_Data_Table.FindIndex(x => x.StringText == t.String_Data_Table[i].StringText) + index_offset];
                        TlkLookupTable.Add(i, new Tuple <string, string>(t.String_Data_Table[i].StringText, randomString.StringText));
                        t.String_Data_Table[i] = randomString;
                    }
                    catch (Exception ex)
                    {
                        if (ex is IndexOutOfRangeException || ex is ArgumentOutOfRangeException)
                        {
                            continue; //ignoring extreme cases
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            }
            else
            {
                TLK t_orig = new TLK(paths.dialog);
                Randomize.FisherYatesShuffle(t.String_Data_Table);

                for (int i = 0; i < t.String_Data_Table.Count; i++)
                {
                    TlkLookupTable.Add(i, new Tuple <string, string>(t_orig.String_Data_Table[i].StringText, t.String_Data_Table[i].StringText));
                }
            }

            t.WriteToFile(paths.dialog);
        }
コード例 #9
0
        /// <summary>
        /// Copy backup module files to the modules directory based on the current shuffle.
        /// </summary>
        /// <param name="paths">KPaths object for this game.</param>
        private static void WriteFilesToModulesDirectory(KPaths paths)
        {
            // Copy shuffled modules into the base directory.
            foreach (var name in LookupTable)
            {
                File.Copy($"{paths.modules_backup}{name.Key}.rim", $"{paths.modules}{name.Value}.rim", true);
                File.Copy($"{paths.modules_backup}{name.Key}_s.rim", $"{paths.modules}{name.Value}_s.rim", true);
                File.Copy($"{paths.lips_backup}{name.Key}_loc.mod", $"{paths.lips}{name.Value}_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);
            }
        }
コード例 #10
0
        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);
            }
        }
コード例 #11
0
        /// <summary>
        /// Replace file data 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 rFile to update.</param>
        /// <param name="rawData">File data to store in the rFile.</param>
        private static void ReplaceSRimFileData(KPaths paths, string area, string label, byte[] rawData)
        {
            // Find the files associated with this area.
            var area_files = paths.FilesInModules.Where(fi => fi.Name.Contains(LookupTable[area]));

            foreach (FileInfo file in area_files)
            {
                // Skip any files that don't end in "s.rim".
                if (file.Name[file.Name.Length - 5] != 's')
                {
                    continue;
                }

                // Check the RIM's File_Table for any rFiles with the given label.
                RIM rim    = new RIM(file.FullName);
                var rFiles = rim.File_Table.Where(x => x.Label == label);
                foreach (RIM.rFile rFile in rFiles)
                {
                    rFile.File_Data = rawData;
                }

                rim.WriteToFile(file.FullName);
            }
        }
コード例 #12
0
        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();
        }
コード例 #13
0
        public static void sound_rando(KPaths paths)
        {
            var musicFiles = paths.FilesInMusicBackup;
            var soundFiles = paths.FilesInSoundsBackup;

            // Get file collections
            List <FileInfo> maxMusic = new List <FileInfo>();
            List <FileInfo> maxSound = new List <FileInfo>();

            // Area Music
            List <FileInfo> areaMusic = new List <FileInfo>();

            foreach (var prefix in PrefixListAreaMusic)
            {
                areaMusic.AddRange(musicFiles.Where(f => f.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)));
            }

            switch ((RandomizationLevel)Properties.Settings.Default.RandomizeAreaMusic)
            {
            case RandomizationLevel.Max:
                maxMusic.AddRange(areaMusic);
                break;

            case RandomizationLevel.Type:
                Randomize.RandomizeFiles(areaMusic, paths.music);
                break;

            case RandomizationLevel.Subtype:
            case RandomizationLevel.None:
            default:
                break;
            }

            // Ambient Noise
            List <FileInfo> ambientNoiseMusic = new List <FileInfo>();

            foreach (var prefix in PrefixListNoise)
            {
                ambientNoiseMusic.AddRange(musicFiles.Where(f => f.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)));
            }

            List <FileInfo> ambientNoiseSound = new List <FileInfo>();

            foreach (var prefix in PrefixListNoise)
            {
                ambientNoiseSound.AddRange(soundFiles.Where(f => f.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)));
            }

            switch ((RandomizationLevel)Properties.Settings.Default.RandomizeAmbientNoise)
            {
            case RandomizationLevel.Max:
                maxMusic.AddRange(ambientNoiseMusic);
                maxSound.AddRange(ambientNoiseSound);
                break;

            case RandomizationLevel.Type:
                Randomize.RandomizeFiles(ambientNoiseMusic, paths.music);
                Randomize.RandomizeFiles(ambientNoiseSound, paths.sounds);
                break;

            case RandomizationLevel.Subtype:
            case RandomizationLevel.None:
            default:
                break;
            }

            // Battle Music
            List <FileInfo> battleMusic    = new List <FileInfo>(musicFiles.Where(f => RegexBattleMusic.IsMatch(f.Name)));
            List <FileInfo> battleMusicEnd = new List <FileInfo>(soundFiles.Where(f => RegexBattleMusic.IsMatch(f.Name)));

            switch ((RandomizationLevel)Properties.Settings.Default.RandomizeBattleMusic)
            {
            case RandomizationLevel.Max:
                maxMusic.AddRange(battleMusic);
                maxSound.AddRange(battleMusicEnd);
                break;

            case RandomizationLevel.Type:
                Randomize.RandomizeFiles(battleMusic, paths.music);
                Randomize.RandomizeFiles(battleMusicEnd, paths.sounds);
                break;

            case RandomizationLevel.Subtype:
            case RandomizationLevel.None:
            default:
                break;
            }

            // Cutscene Noise
            List <FileInfo> cutsceneNoise = new List <FileInfo>(musicFiles.Where(f => RegexCutscene.IsMatch(f.Name)));

            cutsceneNoise.RemoveAll(f => f.Name.StartsWith("57.")); // Remove specific exception

            switch ((RandomizationLevel)Properties.Settings.Default.RandomizeCutsceneNoise)
            {
            case RandomizationLevel.Max:
                maxMusic.AddRange(cutsceneNoise);
                break;

            case RandomizationLevel.Type:
                Randomize.RandomizeFiles(cutsceneNoise, paths.music);
                break;

            case RandomizationLevel.Subtype:
            case RandomizationLevel.None:
            default:
                break;
            }

            // Check if NPC and Party Sounds are combined
            List <FileInfo> npcSounds   = new List <FileInfo>(soundFiles.Where(f => RegexNPCSound.IsMatch(f.Name)));
            List <FileInfo> partySounds = new List <FileInfo>(soundFiles.Where(f => RegexPartySound.IsMatch(f.Name)));

            //if (MixNpcAndPartySounds) // Functionality Disabled
            //{
            //    npcSounds.AddRange(partySounds);
            //}
            //else
            {
                // Party Sounds (if not mixing)
                switch ((RandomizationLevel)Properties.Settings.Default.RandomizePartySounds)
                {
                case RandomizationLevel.Max:
                    maxSound.AddRange(partySounds);
                    break;

                case RandomizationLevel.Type:
                    Randomize.RandomizeFiles(partySounds, paths.sounds);
                    break;

                case RandomizationLevel.Subtype:
                    RandomizeSoundActions(partySounds, paths.sounds);
                    break;

                case RandomizationLevel.None:
                default:
                    break;
                }
            }

            //// NPC Sounds (or both if mixing) // Functionality Disabled
            //switch (RandomizeNpcSounds)
            //{
            //    case RandomizationLevel.Max:
            //        maxSound.AddRange(npcSounds);
            //        break;
            //    case RandomizationLevel.Type:
            //        Randomize.RandomizeFiles(npcSounds, SoundsPath);
            //        break;
            //    case RandomizationLevel.Subtype:
            //        RandomizeSoundActions(npcSounds, SoundsPath);
            //        break;
            //    case RandomizationLevel.None:
            //    default:
            //        break;
            //}

            // Max Randomizations
            if (maxMusic.Any())
            {
                Randomize.RandomizeFiles(maxMusic, paths.music);
            }
            if (maxSound.Any())
            {
                Randomize.RandomizeFiles(maxSound, paths.sounds);
            }
        }
コード例 #14
0
        //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);
            }
        }
コード例 #15
0
        public static void item_rando(KPaths paths)
        {
            // Prepare lists for new randomization.
            Max_Rando.Clear();
            Type_Lists.Clear();
            LookupTable.Clear();

            // Load KEY file.
            KEY k = new KEY(paths.chitin);

            // Handle categories
            HandleCategory(k, ArmbandsRegs, Properties.Settings.Default.RandomizeArmbands);
            HandleCategory(k, ArmorRegs, Properties.Settings.Default.RandomizeArmor);
            HandleCategory(k, BeltsRegs, Properties.Settings.Default.RandomizeBelts);
            HandleCategory(k, BlastersRegs, Properties.Settings.Default.RandomizeBlasters);
            HandleCategory(k, HidesRegs, Properties.Settings.Default.RandomizeHides);
            HandleCategory(k, CreatureRegs, Properties.Settings.Default.RandomizeCreature);
            HandleCategory(k, DroidRegs, Properties.Settings.Default.RandomizeDroid);
            HandleCategory(k, GlovesRegs, Properties.Settings.Default.RandomizeGloves);
            HandleCategory(k, GrenadesRegs, Properties.Settings.Default.RandomizeGrenades);
            HandleCategory(k, ImplantsRegs, Properties.Settings.Default.RandomizeImplants);
            HandleCategory(k, LightsabersRegs, Properties.Settings.Default.RandomizeLightsabers);
            HandleCategory(k, MaskRegs, Properties.Settings.Default.RandomizeMask);
            HandleCategory(k, MeleeRegs, Properties.Settings.Default.RandomizeMelee);
            HandleCategory(k, MinesRegs, Properties.Settings.Default.RandomizeMines);
            HandleCategory(k, PazRegs, Properties.Settings.Default.RandomizePaz);
            HandleCategory(k, StimsRegs, Properties.Settings.Default.RandomizeStims);
            HandleCategory(k, UpgradeRegs, Properties.Settings.Default.RandomizeUpgrade);

            // Handle Various
            switch (Properties.Settings.Default.RandomizeVarious)
            {
            default:
            case RandomizationLevel.None:
                break;

            case RandomizationLevel.Type:
                List <string> type = new List <string>(k.KeyTable.Where(x => Matches_None(x.ResRef) && !Is_Forbidden(x.ResRef) && x.ResourceType == (short)ResourceType.UTI).Select(x => x.ResRef));
                Type_Lists.Add(type);
                break;

            case RandomizationLevel.Max:
                Max_Rando.AddRange(k.KeyTable.Where(x => Matches_None(x.ResRef) && !Is_Forbidden(x.ResRef) && x.ResourceType == (short)ResourceType.UTI).Select(x => x.ResRef));
                break;
            }

            // Omitted Items
            foreach (var item in Globals.OmitItems)
            {
                LookupTable.Add(new Tuple <string, string>(item, item));
            }

            // Max Rando
            List <string> Max_Rando_Iterator = new List <string>(Max_Rando);

            Randomize.FisherYatesShuffle(Max_Rando);
            int j = 0;

            foreach (KEY.KeyEntry ke in k.KeyTable.Where(x => Max_Rando_Iterator.Contains(x.ResRef)))
            {
                LookupTable.Add(new Tuple <string, string>(ke.ResRef, Max_Rando[j]));
                ke.ResRef = Max_Rando[j];
                j++;
            }

            // Type Rando
            foreach (List <string> li in Type_Lists)
            {
                List <string> type_copy = new List <string>(li);
                Randomize.FisherYatesShuffle(type_copy);
                j = 0;
                foreach (KEY.KeyEntry ke in k.KeyTable.Where(x => li.Contains(x.ResRef)))
                {
                    LookupTable.Add(new Tuple <string, string>(ke.ResRef, type_copy[j]));
                    ke.ResRef = type_copy[j];
                    j++;
                }
            }

            k.WriteToFile(paths.chitin);
        }
コード例 #16
0
        public static void sound_rando(KPaths paths)
        {
            // Prepare lists for new randomization.
            MusicLookupTable.Clear();
            SoundLookupTable.Clear();

            // Get file collections
            List <FileInfo> maxMusic   = new List <FileInfo>();
            List <FileInfo> maxSound   = new List <FileInfo>();
            List <FileInfo> musicFiles = new List <FileInfo>();
            List <FileInfo> soundFiles = new List <FileInfo>();

            if (Directory.Exists(paths.music_backup))
            {
                musicFiles = paths.FilesInMusicBackup.ToList();
            }
            if (Directory.Exists(paths.sounds_backup))
            {
                soundFiles = paths.FilesInSoundsBackup.ToList();
            }

            // Area Music
            List <FileInfo> areaMusic = new List <FileInfo>();

            foreach (var prefix in PrefixListAreaMusic)
            {
                areaMusic.AddRange(musicFiles.Where(f => f.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)));
            }

            if (Properties.Settings.Default.RemoveDmcaMusic)
            {
                areaMusic.RemoveAll(f => DmcaAreaMusic.Contains(f.Name));   // Remove DMCA music from the area list.
            }

            switch (Properties.Settings.Default.RandomizeAreaMusic)
            {
            case RandomizationLevel.Max:
                maxMusic.AddRange(areaMusic);
                break;

            case RandomizationLevel.Type:
                var randList = Randomize.RandomizeFiles(areaMusic, paths.music);
                AddToMusicLookup(areaMusic, randList);
                break;

            case RandomizationLevel.Subtype:
            case RandomizationLevel.None:
            default:
                break;
            }

            // Ambient Noise
            List <FileInfo> ambientNoiseMusic = new List <FileInfo>();

            foreach (var prefix in PrefixListNoise)
            {
                ambientNoiseMusic.AddRange(musicFiles.Where(f => f.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)));
            }

            List <FileInfo> ambientNoiseSound = new List <FileInfo>();

            foreach (var prefix in PrefixListNoise)
            {
                ambientNoiseSound.AddRange(soundFiles.Where(f => f.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)));
            }

            switch (Properties.Settings.Default.RandomizeAmbientNoise)
            {
            case RandomizationLevel.Max:
                maxMusic.AddRange(ambientNoiseMusic);
                maxSound.AddRange(ambientNoiseSound);
                break;

            case RandomizationLevel.Type:
                var randList = Randomize.RandomizeFiles(ambientNoiseMusic, paths.music);
                AddToMusicLookup(ambientNoiseMusic, randList);

                randList = Randomize.RandomizeFiles(ambientNoiseSound, paths.sounds);
                AddToSoundLookup(ambientNoiseSound, randList);
                break;

            case RandomizationLevel.Subtype:
            case RandomizationLevel.None:
            default:
                break;
            }

            // Battle Music
            List <FileInfo> battleMusic    = new List <FileInfo>(musicFiles.Where(f => RegexBattleMusic.IsMatch(f.Name)));
            List <FileInfo> battleMusicEnd = new List <FileInfo>(soundFiles.Where(f => RegexBattleMusic.IsMatch(f.Name)));

            switch (Properties.Settings.Default.RandomizeBattleMusic)
            {
            case RandomizationLevel.Max:
                maxMusic.AddRange(battleMusic);
                maxSound.AddRange(battleMusicEnd);
                break;

            case RandomizationLevel.Type:
                var randList = Randomize.RandomizeFiles(battleMusic, paths.music);
                AddToMusicLookup(battleMusic, randList);

                randList = Randomize.RandomizeFiles(battleMusicEnd, paths.sounds);
                AddToSoundLookup(battleMusicEnd, randList);
                break;

            case RandomizationLevel.Subtype:
            case RandomizationLevel.None:
            default:
                break;
            }

            // Cutscene Noise
            List <FileInfo> cutsceneNoise = new List <FileInfo>(musicFiles.Where(f => RegexCutscene.IsMatch(f.Name)));

            cutsceneNoise.RemoveAll(f => f.Name.StartsWith("57.")); // Remove specific exception

            switch (Properties.Settings.Default.RandomizeCutsceneNoise)
            {
            case RandomizationLevel.Max:
                maxMusic.AddRange(cutsceneNoise);
                break;

            case RandomizationLevel.Type:
                var randList = Randomize.RandomizeFiles(cutsceneNoise, paths.music);
                AddToMusicLookup(cutsceneNoise, randList);
                break;

            case RandomizationLevel.Subtype:
            case RandomizationLevel.None:
            default:
                break;
            }

            // Check if NPC and Party Sounds are combined
            List <FileInfo> npcSounds   = new List <FileInfo>(soundFiles.Where(f => RegexNPCSound.IsMatch(f.Name)));
            List <FileInfo> partySounds = new List <FileInfo>(soundFiles.Where(f => RegexPartySound.IsMatch(f.Name)));

            //if (MixNpcAndPartySounds) // Functionality Disabled
            //{
            //    npcSounds.AddRange(partySounds);
            //}
            //else
            {
                // Party Sounds (if not mixing)
                switch (Properties.Settings.Default.RandomizePartySounds)
                {
                case RandomizationLevel.Max:
                    maxSound.AddRange(partySounds);
                    break;

                case RandomizationLevel.Type:
                    var randList = Randomize.RandomizeFiles(partySounds, paths.sounds);
                    AddToSoundLookup(partySounds, randList);
                    break;

                case RandomizationLevel.Subtype:
                    RandomizeSoundActions(partySounds, paths.sounds);
                    break;

                case RandomizationLevel.None:
                default:
                    break;
                }
            }

            //// NPC Sounds (or both if mixing) // Functionality Disabled
            //switch (RandomizeNpcSounds)
            //{
            //    case RandomizationLevel.Max:
            //        maxSound.AddRange(npcSounds);
            //        break;
            //    case RandomizationLevel.Type:
            //        Randomize.RandomizeFiles(npcSounds, SoundsPath);
            //        break;
            //    case RandomizationLevel.Subtype:
            //        RandomizeSoundActions(npcSounds, SoundsPath);
            //        break;
            //    case RandomizationLevel.None:
            //    default:
            //        break;
            //}

            // Max Randomizations
            if (maxMusic.Any())
            {
                var randList = Randomize.RandomizeFiles(maxMusic, paths.music);
                AddToMusicLookup(maxMusic, randList);
            }
            if (maxSound.Any())
            {
                var randList = Randomize.RandomizeFiles(maxSound, paths.sounds);
                AddToSoundLookup(maxSound, randList);
            }

            // Overwrite DMCA music with alternatives
            if (Properties.Settings.Default.RemoveDmcaMusic)
            {
                var orig = new List <FileInfo>();
                var rand = new List <FileInfo>();
                foreach (var fi in musicFiles.Where(f => DmcaAreaMusic.Contains(f.Name)))
                {
                    var replacement = areaMusic[Randomize.Rng.Next(areaMusic.Count)];
                    File.Copy(replacement.FullName, Path.Combine(paths.music, fi.Name), true);

                    orig.Add(fi);
                    rand.Add(replacement);
                }
                AddToMusicLookup(orig, rand);
            }
        }
コード例 #17
0
        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);
            }
        }
コード例 #18
0
        // 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);
                    }
                }
            }
        }
コード例 #19
0
        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);
            }
        }
コード例 #20
0
        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);
            }
        }
コード例 #21
0
        public static void texture_rando(KPaths paths)
        {
            // Prepare lists for new randomization.
            MaxRando.Clear();
            TypeLists.Clear();

            // Load in texture pack.
            string pack_name;

            switch (Properties.Settings.Default.TexturePack)
            {
            default:
            case TexturePack.HighQuality:
                pack_name = "\\swpc_tex_tpa.erf";
                break;

            case TexturePack.MedQuality:
                pack_name = "\\swpc_tex_tpb.erf";
                break;

            case TexturePack.LowQuality:
                pack_name = "\\swpc_tex_tpc.erf";
                break;
            }

            ERF e = new ERF(paths.TexturePacks + pack_name);

            foreach (var key in e.Key_List)
            {
                if (!NameLookup.ContainsKey(key.ResID))
                {
                    NameLookup.Add(key.ResID, key.ResRef);
                }
            }

            // Handle categories.
            HandleCategory(e, RegexCubeMaps, Properties.Settings.Default.TextureRandomizeCubeMaps);
            HandleCategory(e, RegexCreatures, Properties.Settings.Default.TextureRandomizeCreatures);
            HandleCategory(e, RegexEffects, Properties.Settings.Default.TextureRandomizeEffects);
            HandleCategory(e, RegexItems, Properties.Settings.Default.TextureRandomizeItems);
            HandleCategory(e, RegexPlanetary, Properties.Settings.Default.TextureRandomizePlanetary);
            HandleCategory(e, RegexNPC, Properties.Settings.Default.TextureRandomizeNPC);
            HandleCategory(e, RegexPlayHeads, Properties.Settings.Default.TextureRandomizePlayHeads);
            HandleCategory(e, RegexPlayBodies, Properties.Settings.Default.TextureRandomizePlayBodies);
            HandleCategory(e, RegexPlaceables, Properties.Settings.Default.TextureRandomizePlaceables);
            HandleCategory(e, RegexParty, Properties.Settings.Default.TextureRandomizeParty);
            HandleCategory(e, RegexStunt, Properties.Settings.Default.TextureRandomizeStunt);
            HandleCategory(e, RegexVehicles, Properties.Settings.Default.TextureRandomizeVehicles);
            HandleCategory(e, RegexWeapons, Properties.Settings.Default.TextureRandomizeWeapons);

            // Handle other.
            switch (Properties.Settings.Default.TextureRandomizeOther)
            {
            default:
            case RandomizationLevel.None:
                break;     // Do nothing.

            case RandomizationLevel.Type:
                List <int> type = new List <int>(e.Key_List.Where(x => Matches_None(x.ResRef) && !Is_Forbidden(x.ResRef)).Select(x => x.ResID));
                TypeLists.Add(type);
                break;

            case RandomizationLevel.Max:
                MaxRando.AddRange(e.Key_List.Where(x => Matches_None(x.ResRef) && !Is_Forbidden(x.ResRef)).Select(x => x.ResID));
                break;
            }

            // Max Rando.
            List <int> Max_Rando_Iterator = new List <int>(MaxRando);

            Randomize.FisherYatesShuffle(MaxRando);
            int j = 0;

            foreach (ERF.Key k in e.Key_List.Where(x => Max_Rando_Iterator.Contains(x.ResID)))
            {
                LookupTable.Add(k.ResID, MaxRando[j]);
                k.ResID = MaxRando[j];
                j++;
            }

            // Type Rando.
            foreach (List <int> li in TypeLists)
            {
                List <int> type_copy = new List <int>(li);
                Randomize.FisherYatesShuffle(type_copy);
                j = 0;
                foreach (ERF.Key k in e.Key_List.Where(x => li.Contains(x.ResID)))
                {
                    LookupTable.Add(k.ResID, type_copy[j]);
                    k.ResID = type_copy[j];
                    j++;
                }
            }

            e.WriteToFile(paths.TexturePacks + pack_name);
        }
コード例 #22
0
        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");
                }
            }
コード例 #23
0
        /// <summary>
        /// Populates and shuffles the the modules flagged to be randomized. Returns true if override files should be added.
        /// </summary>
        /// <param name="paths">KPaths object for this game.</param>
        public static void Module_rando(KPaths paths)
        {
            // Reset digraph reachability settings.
            Digraph.ResetSettings();
            LookupTable.Clear();

            // Split the Bound modules into their respective lists.
            bool reachable  = false;
            int  iterations = 0;

            // Only shuffle if there is more than 1 module in the shuffle.
            if (Globals.BoundModules.Count(x => !x.Omitted) > 1)
            {
                if (Properties.Settings.Default.UseRandoRules ||
                    Properties.Settings.Default.VerifyReachability)
                {
                    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                    sw.Start();

                    while (!reachable && iterations < MAX_ITERATIONS)
                    {
                        iterations++;

                        Console.WriteLine($"Iteration {iterations}:");

                        CreateLookupTableShuffle();

                        Digraph.SetRandomizationLookup(LookupTable);

                        if (Properties.Settings.Default.UseRandoRules)
                        {
                            // Skip to the next iteration if the rules are violated.
                            if (AreRulesViolated())
                            {
                                continue;
                            }
                        }

                        if (Properties.Settings.Default.VerifyReachability)
                        {
                            Digraph.CheckReachability();
                            reachable = Digraph.IsGoalReachable();
                        }
                        else
                        {
                            reachable = true;
                        }
                    }

                    if (Properties.Settings.Default.VerifyReachability)
                    {
                        if (reachable)
                        {
                            var message = $"Reachable solution found after {iterations} shuffles. Time elapsed: {sw.Elapsed}";
                            Console.WriteLine(message);
                        }
                        else
                        {
                            // Throw an exception if not reachable.
                            var message = $"No reachable solution found over {iterations} shuffles. Time elapsed: {sw.Elapsed}";
                            Console.WriteLine(message);
                            throw new TimeoutException(message);
                        }
                    }

                    //digraph.WriteReachableToConsole();
                    Console.WriteLine();
                }
                else
                {
                    CreateLookupTableShuffle();
                }
            }
            else
            {
                CreateLookupTableNoShuffle();
            }

            WriteFilesToModulesDirectory(paths);

            // Write additional override files (and unlock galaxy map).
            WriteOverrideFiles(paths);

            // Fix warp coordinates.
            if (Properties.Settings.Default.ModuleExtrasValue.HasFlag(ModuleExtras.FixCoordinates))
            {
                FixWarpCoordinates(paths);
            }

            // Fixed Rakata riddle Man in Mind Prison.
            if (Properties.Settings.Default.ModuleExtrasValue.HasFlag(ModuleExtras.FixMindPrison))
            {
                FixMindPrison(paths);
            }

            // Unlock locked doors or elevators.
            UnlockDoors(paths);

            // Vulkar Spice Lab Transition
            if (Properties.Settings.Default.ModuleExtrasValue.HasFlag(ModuleExtras.VulkarSpiceLZ))
            {
                var vulk_files = paths.FilesInModules.Where(fi => fi.Name.Contains(LookupTable[AREA_TAR_VULK_BASE]));
                foreach (FileInfo fi in vulk_files)
                {
                    // Skip any files that end in "s.rim".
                    if (fi.Name[fi.Name.Length - 5] == 's')
                    {
                        continue;
                    }

                    RIM r_vul = new RIM(fi.FullName);
                    r_vul.File_Table.FirstOrDefault(x => x.Label == LABEL_TAR_VULK_GIT && x.TypeID == (int)ResourceType.GIT).File_Data = Properties.Resources.m10aa;

                    r_vul.WriteToFile(fi.FullName);
                }
            }
        }
コード例 #24
0
        /// <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);
            }
        }