private static void Bootup() { if (Egcb_MutableMutations.bStarted == true) { return; } Egcb_MutableMutations.bStarted = true; Egcb_MutableMutations.OptionsList = new List <string>(); Egcb_MutableMutations.CachedOptionValues = new Dictionary <string, string>(); Egcb_MutableMutations.MutationData = new List <MutationCategory>(); Egcb_MutableMutations.MutationCategoryDict = new Dictionary <string, MutationCategory>(); //Load mutation data from the default Mutations.xml file. Only vanilla mods are supported for now. // While I considered loading data from other mods, it seems like that could // cause issues if the user uninstalled one of those mods later and MutableMutations then tried to load data for that mod's mutations. // A possible solution later would be to directly update the Mutations.xml file in that mod's folder, instead of generating an override // (that would probably be necessary anyway because I don't think we can guarantee the order Mods are loaded.) Egcb_MutableMutations.LoadVanillaMutations(); //Create our custom option list for each mutation, adding them to the game's Option list Egcb_MutableMutations.CreateOptionsList(); //Generate a custom Mutations.xml file in our mod's directory. This is unfortunately necessary because the game reloads Mutations.xml //files every time that the player re-enters the Character Generation screen, so we can't just change the Costs in MutationFactory Egcb_MutableMutations.ApplyMutationOptions(true); //start the MonoBehavior Coroutine to poll for the options menu. We'll update Mutations.xml every time the user changes mutations options Egcb_MutableMutations.StartOptionsMonitor(); }
private static MutationCategory LoadCategoryNode(XmlTextReader stream) { MutationCategory mutationCategory = new MutationCategory { Name = stream.GetAttribute("Name"), DisplayName = stream.GetAttribute("DisplayName"), Help = stream.GetAttribute("Help"), Stat = stream.GetAttribute("Stat"), Property = stream.GetAttribute("Property"), ForceProperty = stream.GetAttribute("ForceProperty") }; while (stream.Read()) { if (stream.Name == "mutation") { MutationEntry mutationEntry = Egcb_MutableMutations.LoadMutationNode(stream); mutationEntry.Category = mutationCategory; if (!mutationEntry.Prerelease || Options.GetOption("OptionEnablePrereleaseContent", string.Empty) == "Yes") { mutationCategory.Entries.Add(mutationEntry); } } if (stream.NodeType == XmlNodeType.EndElement && (stream.Name == string.Empty || stream.Name == "category")) { return(mutationCategory); } } return(mutationCategory); }
public Egcb_MutableMutations() { if (Options.OptionsByCategory.Count <= 0 || Options.OptionsByID.Count <= 0) { Debug.Log("Mutable Mutations Mod - Failed to initialize mod: Options dictionary does not exist."); return; } Egcb_MutableMutations.Bootup(); }
public static void ResetMutationCosts() { foreach (MutationCategory mc in Egcb_MutableMutations.MutationData) { foreach (MutationEntry me in mc.Entries) { //reset all mutation costs to the value specified in the core Mutations.xml file string opName = Egcb_MutableMutations.GetOptionNameForMutationCost(me); Options.SetOption(opName, Egcb_MutableMutations.GetDefaultCostForMutationValueArray(me)); } } Debug.Log("Mutable Mutations Mod - Reset all mutation costs to default."); }
//Most of LoadVanillaMutations, LoadCategoryNode, and LoadMutationNode were adapted directly from the game's MutationFactory code private static void LoadVanillaMutations() { Egcb_MutableMutations.MutationData.Clear(); Egcb_MutableMutations.MutationCategoryDict.Clear(); using (XmlTextReader stream = DataManager.GetStreamingAssetsXMLStream("Mutations.xml")) { stream.WhitespaceHandling = WhitespaceHandling.None; while (stream.Read()) { if (stream.Name == "mutations") { while (stream.Read()) { if (stream.Name == "category") { MutationCategory mutationCategory = Egcb_MutableMutations.LoadCategoryNode(stream); if (mutationCategory.Name[0] == '-') { if (Egcb_MutableMutations.MutationCategoryDict.ContainsKey(mutationCategory.Name.Substring(1))) { MutationCategory cat = MutationFactory.CategoriesByName[mutationCategory.Name.Substring(1)]; Egcb_MutableMutations.MutationCategoryDict.Remove(mutationCategory.Name.Substring(1)); Egcb_MutableMutations.MutationData.Remove(cat); } } else if (Egcb_MutableMutations.MutationCategoryDict.ContainsKey(mutationCategory.Name)) { Egcb_MutableMutations.MutationCategoryDict[mutationCategory.Name].MergeWith(mutationCategory); } else { Egcb_MutableMutations.MutationCategoryDict.Add(mutationCategory.Name, mutationCategory); Egcb_MutableMutations.MutationData.Add(mutationCategory); } } if (stream.NodeType == XmlNodeType.EndElement && (stream.Name == string.Empty || stream.Name == "mutations")) { break; } } } if (stream.NodeType == XmlNodeType.EndElement && (stream.Name == string.Empty || stream.Name == "mutations")) { break; } } stream.Close(); } }
public static void ReapplyOptions() { //the user selected the option to reset all mutation costs to default if (Options.GetOption(Egcb_MutableMutations.ResetMutationValueOptionID) == "Yes") { Options.SetOption(Egcb_MutableMutations.ResetMutationValueOptionID, "No"); Egcb_MutableMutations.ResetMutationCosts(); Egcb_MutableMutations.ApplyMutationOptions(false); } //check if any mutation cost settings were changed, and if so, rebuild Mutations.xml else if (!Egcb_MutableMutations.ValidateCache()) { Egcb_MutableMutations.ApplyMutationOptions(false); } }
private static void CreateOptionsList() { Egcb_MutableMutations.OptionsList.Clear(); //create a reset option to restore game defaults GameOption resetOp = new GameOption(); resetOp.ID = Egcb_MutableMutations.ResetMutationValueOptionID; resetOp.DisplayText = "Reset all mutation costs to default (after closing Options)"; resetOp.Category = Egcb_MutableMutations.OptionsCategoryName; resetOp.Type = "Checkbox"; resetOp.Default = "No"; Egcb_MutableMutations.OptionsList.Add(resetOp.ID); Egcb_MutableMutations.AddNewGameOption(resetOp); foreach (MutationCategory mc in Egcb_MutableMutations.MutationData) { string mutationCategoryName = ConsoleLib.Console.ColorUtility.StripFormatting(mc.DisplayName).TrimEnd('s'); foreach (MutationEntry me in mc.Entries) { string optionName = Egcb_MutableMutations.GetOptionNameForMutationCost(me); Egcb_MutableMutations.OptionsList.Add(optionName); if (Options.OptionsByID.ContainsKey(optionName) || me.Cost == 0) //also skip 0 cost vanilla entries, if they exist, because we won't really know what Values range to use { continue; } //option doesn't exist, so we'll create it GameOption gameOption = new GameOption(); gameOption.ID = optionName; gameOption.DisplayText = Egcb_MutableMutations.GetMutationCostOptionDisplayText(me); gameOption.Category = Egcb_MutableMutations.OptionsCategoryName; gameOption.Type = "Combo"; gameOption.Values = Egcb_MutableMutations.GetCostValueArrayForMutation(me); gameOption.Default = Egcb_MutableMutations.GetDefaultCostForMutationValueArray(me); //add to game Options Egcb_MutableMutations.AddNewGameOption(gameOption); } } }
private static void ApplyMutationOptions(bool bInitialLoad) { if (bInitialLoad) { Debug.Log("Mutable Mutations Mod - Generating initial mutation cost settings..."); } else { Debug.Log("Mutable Mutations Mod - Regenerating mutation cost settings..."); } Egcb_MutableMutations.CachedOptionValues.Clear(); using (StreamWriter xmlStream = new StreamWriter(Path.Combine(Egcb_MutableMutations.ModDirectory, "Mutations.xml"), false)) { XmlWriterSettings xmlSettings = new XmlWriterSettings { Indent = true }; using (XmlWriter xmlWriter = XmlWriter.Create(xmlStream, xmlSettings)) { xmlWriter.WriteStartDocument(); xmlWriter.WriteStartElement("mutations"); foreach (MutationCategory mc in Egcb_MutableMutations.MutationData) { xmlWriter.WriteStartElement("category"); xmlWriter.WriteAttributeString("Name", mc.Name); xmlWriter.WriteAttributeString("DisplayName", mc.DisplayName); if (!String.IsNullOrEmpty(mc.Help)) { xmlWriter.WriteAttributeString("Help", mc.Help); } if (!String.IsNullOrEmpty(mc.Stat)) { xmlWriter.WriteAttributeString("Stat", mc.Stat); } if (!String.IsNullOrEmpty(mc.Property)) { xmlWriter.WriteAttributeString("Property", mc.Property); } if (!String.IsNullOrEmpty(mc.ForceProperty)) { xmlWriter.WriteAttributeString("ForceProperty", mc.ForceProperty); } foreach (MutationEntry me in mc.Entries) { xmlWriter.WriteStartElement("mutation"); string mutationOptionName = Egcb_MutableMutations.GetOptionNameForMutationCost(me); string mutationOptionCost = Options.GetOption(mutationOptionName, String.Empty).Trim(); mutationOptionCost = (String.IsNullOrEmpty(mutationOptionCost) ? me.Cost.ToString() : mutationOptionCost); Egcb_MutableMutations.CachedOptionValues.Add(mutationOptionName, mutationOptionCost); xmlWriter.WriteAttributeString("Name", me.DisplayName); xmlWriter.WriteAttributeString("Cost", mutationOptionCost); if (!String.IsNullOrEmpty(me.Stat)) { xmlWriter.WriteAttributeString("Stat", me.Stat); } if (me.Maximum != -999) { xmlWriter.WriteAttributeString("MaxSelected", me.Maximum.ToString()); } xmlWriter.WriteAttributeString("Class", me.Class); if (!String.IsNullOrEmpty(me.Constructor)) { xmlWriter.WriteAttributeString("Constructor", me.Constructor); } xmlWriter.WriteAttributeString("Exclusions", me.Exclusions); if (me.MaxLevel != -999) { xmlWriter.WriteAttributeString("MaxLevel", me.MaxLevel.ToString()); } if (!String.IsNullOrEmpty(me.Property)) { xmlWriter.WriteAttributeString("Property", me.Property); } if (!String.IsNullOrEmpty(me.ForceProperty)) { xmlWriter.WriteAttributeString("ForceProperty", me.ForceProperty); } if (!String.IsNullOrEmpty(me.BearerDescription)) { xmlWriter.WriteAttributeString("BearerDescription", me.BearerDescription); } xmlWriter.WriteAttributeString("Code", me.MutationCode); if (me.Prerelease == true) { xmlWriter.WriteAttributeString("Prerelease", "true"); } xmlWriter.WriteFullEndElement(); //important to write FullEndElement, game can't parse self-closing element in Mutations.xml yet } xmlWriter.WriteFullEndElement(); } xmlWriter.WriteEndDocument(); xmlWriter.Flush(); xmlWriter.Close(); } xmlStream.Flush(); xmlStream.Close(); } }