Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Smol Randomizer v0.1.1
Smol_Randomizer.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using GlobalEnums; using GlobalSettings; using HarmonyLib; using HutongGames.PlayMaker; using HutongGames.PlayMaker.Actions; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Silksong.DataManager; using Silksong.ModMenu.Elements; using Silksong.ModMenu.Models; using Silksong.ModMenu.Plugin; using Silksong.ModMenu.Screens; using Smol_Randomizer.Randomizers; using Smol_Randomizer.Settings; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Ashilstraza")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Randomizer for Miscellanious Smol Things")] [assembly: AssemblyFileVersion("0.1.1.0")] [assembly: AssemblyInformationalVersion("0.1.1+5f70d32d08c8a1e4d5f0e8fee639c8795e271cb8")] [assembly: AssemblyProduct("Smol_Randomizer")] [assembly: AssemblyTitle("Smol_Randomizer")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Ashilstraza/Smol_Randomizer")] [assembly: AssemblyVersion("0.1.1.0")] [module: RefSafetyRules(11)] namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } internal sealed class ConfigurationManagerAttributes { public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput); public bool? ShowRangeAsPercent; public Action<ConfigEntryBase> CustomDrawer; public CustomHotkeyDrawerFunc CustomHotkeyDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func<object, string> ObjToStr; public Func<string, object> StrToObj; } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Embedded] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Embedded] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Microsoft.CodeAnalysis { [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace Smol_Randomizer { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("ashilstraza.randomizer.cute", "Smol Randomizer", "0.1.0")] public class CuteRandoCore : BaseUnityPlugin, IModMenuInterface, IModMenuCustomMenu, IRawSaveDataMod { public const string GUID = "ashilstraza.randomizer.cute"; public const string MODNAME = "Smol Randomizer"; public const string VERSION = "0.1.0"; private bool updateActiveLimitRegions; private bool updateOnFirstSceneFrame; private static readonly HashSet<string> allRandomizers = new HashSet<string>(); private static readonly HashSet<Randomizer_Info> allRandomizerActions = new HashSet<Randomizer_Info>(); internal static bool testing = false; internal static bool randomize = true; internal static readonly Harmony harmony = new Harmony("ashilstraza.randomizer.cute"); internal static SettingMenu cuteRandomizerSettingWindow; internal static Random noSeedRNG = new Random(); private static readonly Dictionary<string, Action<ICurrencyLimitRegion>> activeLimitRegions = new Dictionary<string, Action<ICurrencyLimitRegion>>(); private static readonly Dictionary<string, Action<Scene, LoadSceneMode>> activeOnSceneLoad = new Dictionary<string, Action<Scene, LoadSceneMode>>(); private static readonly Dictionary<string, Action> activeGameStartup = new Dictionary<string, Action>(); private static readonly Dictionary<string, Action> activeGameShutdown = new Dictionary<string, Action>(); private static readonly Dictionary<string, Action> activeOnFirstSceneFrame = new Dictionary<string, Action>(); private static readonly Dictionary<string, string> randomizerDescriptions = new Dictionary<string, string>(); public static readonly string[] bossFilter = new string[10] { "Lace", "Phantom", "Silk Boss", "Bone Beast", "Trobbio", "Shakra", "Mapper", "Forebrother", "Garmond", "SG_head" }; public static string DataLocation { get; private set; } = ""; public bool HasSaveData => Smol_Randomizer.Settings.Settings.SaveData != null; private void Awake() { DataLocation = ((BaseUnityPlugin)this).Info.Location.TrimEnd("\\\\Smol_Randomizer.dll".ToCharArray()) + "\\Smol_Randomizer"; Smol_Randomizer.Settings.Settings.Init(((BaseUnityPlugin)this).Config); _ = Enemy_Currency_Rando.Instance; _ = World_Currency_Drop_Rando.Instance; _ = Enemy_Health_Rando.Instance; _ = Enemy_Damage_Rando.Instance; _ = Hero_Damage_Rando.Instance; _ = Enemy_Size_Rando.Instance; } private void Start() { SceneManager.sceneLoaded += OnSceneLoaded; foreach (KeyValuePair<string, Action> item in activeGameStartup) { item.Value(); } } private void Update() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)GameManager.SilentInstance == (Object)null || !randomize || (((Object)(object)GameManager.instance.sm != (Object)null) ? new SceneType?(GameManager.instance.sm.sceneType) : ((SceneType?)null)) != (SceneType?)0) { return; } if (updateActiveLimitRegions) { foreach (ICurrencyLimitRegion item in (HashSet<ICurrencyLimitRegion>)Traverse.Create<CurrencyObjectLimitRegion>().Field("_activeRegions").GetValue()) { foreach (KeyValuePair<string, Action<ICurrencyLimitRegion>> activeLimitRegion in activeLimitRegions) { activeLimitRegion.Value(item); } } updateActiveLimitRegions = false; } if (!updateOnFirstSceneFrame) { return; } foreach (KeyValuePair<string, Action> item2 in activeOnFirstSceneFrame) { item2.Value(); } updateOnFirstSceneFrame = false; } internal static void UpdateSettings(object sender, EventArgs args) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) randomize = Smol_Randomizer.Settings.Settings.EnableRandomizer; if (!randomize) { SmolRandomizerMenuBuilder.Enabled = SmolRandomizerMenuBuilder.LightGray; SmolRandomizerMenuBuilder.Disabled = SmolRandomizerMenuBuilder.LightGray; } else { SettingMenu.ChangeColors(Smol_Randomizer.Settings.Settings.EnabledRandomizerColors); } SettingMenu.thisSettingMenu?.UpdateAllSubMenuColors(); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!randomize) { return; } foreach (KeyValuePair<string, Action<Scene, LoadSceneMode>> item in activeOnSceneLoad) { item.Value(scene, mode); } updateOnFirstSceneFrame = true; updateActiveLimitRegions = true; } private void OnApplicationQuit() { foreach (KeyValuePair<string, Action> item in activeGameShutdown) { item.Value(); } } public AbstractMenuScreen BuildCustomMenu() { cuteRandomizerSettingWindow = new SettingMenu(LocalizedText.op_Implicit("Smol Randomizer")); return (AbstractMenuScreen)(object)cuteRandomizerSettingWindow; } public static string GetRandoDescription(string randoName) { randomizerDescriptions.TryGetValue(randoName, out string value); return value; } internal static void AddRandoDescription(string randoName, string randoDescription) { randomizerDescriptions.Add(randoName, randoDescription); } public void WriteSaveData(Stream saveFile) { RandoPerSaveData.Saving(); string value = JsonConvert.SerializeObject((object)Smol_Randomizer.Settings.Settings.SaveData, (Formatting)1); using StreamWriter streamWriter = new StreamWriter(saveFile); try { streamWriter.Write(value); } catch (Exception ex) { Console.Error.WriteLine("[Smol Randomizer] Exception encountered, unable to write per-save data for current save slot.\n" + ex.Message); } } public void ReadSaveData(Stream? saveFile) { if (saveFile == null) { Smol_Randomizer.Settings.Settings.SaveData = new RandoPerSaveData(); return; } using StreamReader streamReader = new StreamReader(saveFile); try { Smol_Randomizer.Settings.Settings.SaveData = JsonConvert.DeserializeObject<RandoPerSaveData>(streamReader.ReadToEnd()) ?? new RandoPerSaveData(); } catch (Exception ex) { Console.Error.WriteLineAsync("[Smol Randomizer] Exception encountered, unable to load per-save data for current save slot.\n" + ex.Message); } } internal static void ImportJsonFile(string fileName, out string importTarget) { if (!File.Exists(DataLocation + "\\\\" + fileName + ".json")) { importTarget = ""; return; } try { importTarget = File.ReadAllText(DataLocation + "\\\\" + fileName + ".json"); } catch (Exception ex) { Console.Error.WriteLine("Exception encountered, unable to import " + fileName + ".\n" + ex.Message); importTarget = ""; } } internal static void ExportJsonFile(string fileName, object exportTarget) { string contents = JsonConvert.SerializeObject(exportTarget, (Formatting)1); try { File.WriteAllText(DataLocation + "\\\\" + fileName + ".json", contents); } catch (Exception ex) { Console.Error.WriteLine("Exception encountered, unable to export " + fileName + ".\n" + ex.Message); } } public static bool RegisterRandomizer(Randomizer_Info randomizer) { if (randomizer == null) { throw new ArgumentNullException("randomizer", "Unable to register null as a randomizer."); } if (randomizer.Name == null) { throw new ArgumentException("Randomizer has a null name."); } if (randomizer.Method == null) { throw new ArgumentException("Randomizer has a null action."); } foreach (Randomizer_Info allRandomizerAction in allRandomizerActions) { if (randomizer.Name == allRandomizerAction.Name) { Console.Error.WriteLine("[Smol Randomizer] Unable to register randomizer action: There already is a randomizer with the same name."); } else if (randomizer.Method == allRandomizerAction.Method) { Console.Error.WriteLine("[Smol Randomizer] Unable to register randomizer action: Duplicate action."); } } if (!allRandomizerActions.Add(randomizer)) { return false; } if (allRandomizers.Add(randomizer.Name)) { Console.WriteLine("[Smol Randomizer] Registering randomizer: " + randomizer.Name + "."); } switch (randomizer.RandomizerType) { case RandomizerEventType.ActiveLimitRegion: activeLimitRegions.Add(randomizer.Name, (Action<ICurrencyLimitRegion>)DelegateHelper(typeof(Action<ICurrencyLimitRegion>), randomizer.Method, randomizer.Object)); break; case RandomizerEventType.OnSceneLoad: activeOnSceneLoad.Add(randomizer.Name, (Action<Scene, LoadSceneMode>)DelegateHelper(typeof(Action<Scene, LoadSceneMode>), randomizer.Method, randomizer.Object)); break; case RandomizerEventType.OnFirstSceneFrame: activeOnFirstSceneFrame.Add(randomizer.Name, (Action)DelegateHelper(typeof(Action), randomizer.Method, randomizer.Object)); break; case RandomizerEventType.GameStartup: activeGameStartup.Add(randomizer.Name, (Action)DelegateHelper(typeof(Action), randomizer.Method, randomizer.Object)); break; case RandomizerEventType.GameShutdown: activeGameShutdown.Add(randomizer.Name, (Action)DelegateHelper(typeof(Action), randomizer.Method, randomizer.Object)); break; default: Console.Error.WriteLine("Unimplemented entryType"); allRandomizerActions.Remove(randomizer); return false; case RandomizerEventType.ActiveEnemy: case RandomizerEventType.ActiveHeroDamager: break; } return true; static Delegate DelegateHelper(Type type, MethodInfo methodInfo, object? firstArgument = null) { if (firstArgument != null) { return Delegate.CreateDelegate(type, firstArgument, methodInfo); } return Delegate.CreateDelegate(type, methodInfo); } } public static bool UnregisterRandomizer(Randomizer_Info randomizer) { if (randomizer == null) { throw new ArgumentNullException("randomizer", "Not able to unregister a null randomizer."); } if (randomizer.Name == null) { throw new ArgumentException("Not able to unregister a randomizer with a null name."); } if (!allRandomizerActions.Remove(randomizer)) { return false; } Console.WriteLine(string.Format("[{0}] Unregistering randomizer event: {1} from {2}.", "Smol Randomizer", randomizer.RandomizerType, randomizer.Name)); switch (randomizer.RandomizerType) { case RandomizerEventType.ActiveLimitRegion: activeLimitRegions.Remove(randomizer.Name); break; case RandomizerEventType.OnSceneLoad: activeOnSceneLoad.Remove(randomizer.Name); break; case RandomizerEventType.OnFirstSceneFrame: activeOnFirstSceneFrame.Remove(randomizer.Name); break; case RandomizerEventType.GameStartup: activeGameStartup.Remove(randomizer.Name); break; case RandomizerEventType.GameShutdown: activeGameShutdown.Remove(randomizer.Name); break; default: Console.Error.WriteLine("Unimplemented entryType"); return false; case RandomizerEventType.ActiveEnemy: case RandomizerEventType.ActiveHeroDamager: break; } if (allRandomizerActions.FirstOrDefault((Randomizer_Info x) => x.Name == randomizer.Name) == null) { allRandomizers.Remove(randomizer.Name); } return true; } public static Traverse TraverseHelper(object type, string field) { return Traverse.Create(type).Field(field); } public static float RandoHelper((float min, float max) tuple, int seed = int.MinValue) { return RandoHelper(tuple.min, tuple.max, seed); } public static int RandoHelper((int min, int max) tuple, int seed = int.MinValue) { return RandoHelper(tuple.min, tuple.max, seed); } public static float RandoHelper(float min, float max, int seed = int.MinValue) { if (seed > int.MinValue) { Random.InitState(seed); return Random.Range(min, max); } return (float)(noSeedRNG.NextDouble() * (double)(max - min) + (double)min); } public static int RandoHelper(int min, int max, int seed = int.MinValue) { checked { if (seed > int.MinValue) { Random.InitState(seed); return Random.Range(min, max + 1); } return noSeedRNG.Next(min, max + 1); } } public static int GetNewSaveSeed() { return Random.Range(-2147483647, int.MaxValue); } public static int RNGSeed(string modifier) { int num = Smol_Randomizer.Settings.Settings.SaveData.SaveSeed; byte[] bytes = Encoding.Unicode.GetBytes(modifier); foreach (byte b in bytes) { num = checked(num + b); } return num; } public static bool IsBoss(HealthManager thing) { if ((Object)(object)thing == (Object)null || ((Component)thing).GetComponent<EnemyDeathEffects>() is EnemyDeathEffectsNoEffect) { return false; } string[] array = bossFilter; foreach (string value in array) { if (((Object)thing).name.Contains(value)) { return true; } } PlayMakerFSM[] components = ((Component)thing).GetComponents<PlayMakerFSM>(); for (int i = 0; i < components.Length; i++) { FsmState[] fsmStates = components[i].FsmStates; foreach (FsmState obj in fsmStates) { if (obj != null && obj.Actions.Any((FsmStateAction action) => action is DisplayBossTitle)) { return true; } } } return false; } } public enum RandomizerEventType : byte { ActiveEnemy, ActiveLimitRegion, OnSceneLoad, OnFirstSceneFrame, GameStartup, GameShutdown, ActiveHeroDamager } public class Randomizer_Info(string name, RandomizerEventType randomizerType, MethodInfo method, object? o = null) { public string Name => name; public RandomizerEventType RandomizerType => randomizerType; public MethodInfo Method => method; public object? Object => o; } } namespace Smol_Randomizer.Settings { public class FloatRange { private float min; private float max; public float Min { get { return min; } set { int num = value.CompareTo(max); if (num > 0) { throw new ArgumentException($"{value} is greater than the maximum value ({max})"); } min = value; } } public float Max { get { return max; } set { int num = value.CompareTo(min); if (num < 0) { throw new ArgumentException($"{value} is less than the minimum value ({min})"); } max = value; } } private float Both { get { if (min != max) { return max / min; } return min; } set { min = value; max = value; } } public (float min, float max) AsTuple() { return (min: min, max: max); } public FloatRange(float min, float max) { if (min.CompareTo(max) <= 0) { this.min = min; this.max = max; return; } throw new ArgumentException($"{min} is greater than the maximum value ({max})"); } public static implicit operator float(FloatRange fr) { return fr.Both; } public static explicit operator FloatRange(float f) { return new FloatRange(f, f); } public bool ContainsValue(float value) { if (value.CompareTo(min) >= 0) { return value.CompareTo(max) <= 0; } return false; } public override string ToString() { return $"[{min} - {max}]"; } public static FloatRange Parse(string s) { string[] array = s.Split(new char[4] { '[', ' ', '-', ']' }, StringSplitOptions.RemoveEmptyEntries); return new FloatRange(float.Parse(array[0]), float.Parse(array[1])); } public static FloatRange Parse(string s1, string s2) { float num = float.Parse(s1); float num2 = float.Parse(s2); return new FloatRange(num, num2); } public override bool Equals(object obj) { if (obj is FloatRange floatRange && floatRange.Min == Min && floatRange.Max == Max) { return true; } return false; } public override int GetHashCode() { return HashCode.Combine(min, max); } } public class AcceptableRangeforFloatRange(float minValue, float maxValue) : AcceptableValueBase(typeof(FloatRange)) { public float MinValue { get; } = minValue; public float MaxValue { get; } = maxValue; public override object Clamp(object value) { if (value.GetType() == typeof(FloatRange)) { FloatRange floatRange = (FloatRange)value; if (MinValue.CompareTo(floatRange.Min) > 0) { floatRange.Min = MinValue; } if (MaxValue.CompareTo(floatRange.Max) < 0) { floatRange.Max = MaxValue; } return floatRange; } if (value.GetType() == typeof(float)) { float value2 = (float)value; if (MinValue.CompareTo(value2) > 0) { return MinValue; } if (MaxValue.CompareTo(value2) < 0) { return MaxValue; } return value; } throw new ArgumentException("Unable to clamp an object that is not an IntRange or int"); } public override bool IsValid(object value) { if (value.GetType() == typeof(FloatRange)) { FloatRange floatRange = (FloatRange)value; if (MinValue.CompareTo(floatRange.Min) <= 0) { return MaxValue.CompareTo(floatRange.Max) >= 0; } } else if (value.GetType() == typeof(float)) { float value2 = (float)value; if (MinValue.CompareTo(value2) <= 0) { return MaxValue.CompareTo(value2) >= 0; } } return false; } public override string ToDescriptionString() { return $"# Acceptable value range: From {MinValue} to {MaxValue}"; } } public class IntRange { private int min; private int max; public int Min { get { return min; } set { int num = value.CompareTo(max); if (num > 0) { throw new ArgumentException($"{value} is greater than the maximum value ({max})"); } min = value; } } public int Max { get { return max; } set { int num = value.CompareTo(min); if (num < 0) { throw new ArgumentException($"{value} is less than the minimum value ({min})"); } max = value; } } private int Both { get { if (min != max) { return max / min; } return min; } set { min = value; max = value; } } public (int min, int max) AsTuple() { return (min: min, max: max); } public IntRange(int min, int max) { if (min.CompareTo(max) <= 0) { this.min = min; this.max = max; return; } throw new ArgumentException($"{min} is greater than the maximum value ({max})"); } public static implicit operator int(IntRange ir) { return ir.Both; } public static explicit operator IntRange(int i) { return new IntRange(i, i); } public bool ContainsValue(int value) { if (value.CompareTo(min) >= 0) { return value.CompareTo(max) <= 0; } return false; } public override string ToString() { return $"[{min} - {max}]"; } public static IntRange Parse(string s) { string[] array = s.Split(new char[4] { '[', ' ', '-', ']' }, StringSplitOptions.RemoveEmptyEntries); return new IntRange(int.Parse(array[0]), int.Parse(array[1])); } public static IntRange Parse(string s1, string s2) { int num = int.Parse(s1); int num2 = int.Parse(s2); return new IntRange(num, num2); } public override bool Equals(object obj) { if (obj is IntRange intRange && intRange.Min == Min && intRange.Max == Max) { return true; } return false; } public override int GetHashCode() { return HashCode.Combine(min, max); } } public class AcceptableRangeforIntRange(int minValue, int maxValue) : AcceptableValueBase(typeof(IntRange)) { public int MinValue { get; } = minValue; public int MaxValue { get; } = maxValue; public override object Clamp(object value) { if (value.GetType() == typeof(IntRange)) { IntRange intRange = (IntRange)value; if (MinValue.CompareTo(intRange.Min) > 0) { intRange.Min = MinValue; } if (MaxValue.CompareTo(intRange.Max) < 0) { intRange.Max = MaxValue; } return intRange; } if (value.GetType() == typeof(int)) { int value2 = (int)value; if (MinValue.CompareTo(value2) > 0) { return MinValue; } if (MaxValue.CompareTo(value2) < 0) { return MaxValue; } return value; } throw new ArgumentException("Unable to clamp an object that is not an IntRange or int"); } public override bool IsValid(object value) { if (value.GetType() == typeof(IntRange)) { IntRange intRange = (IntRange)value; if (MinValue.CompareTo(intRange.Min) <= 0) { return MaxValue.CompareTo(intRange.Max) >= 0; } } else if (value.GetType() == typeof(int)) { int value2 = (int)value; if (MinValue.CompareTo(value2) <= 0) { return MaxValue.CompareTo(value2) >= 0; } } return false; } public override string ToDescriptionString() { return $"# Acceptable value range: From {MinValue} to {MaxValue}"; } } internal class SettingMenu : SmolRandomizerMenuBuilder { private readonly HashSet<TextButton> randoMenuButtons = new HashSet<TextButton>(); private static readonly Dictionary<string, bool> preInitSetting = new Dictionary<string, bool>(); internal static SettingMenu thisSettingMenu; private static readonly HashSet<TextButton> randoResetButtons = new HashSet<TextButton>(); public static event Action<string> OnResetClicked; internal SettingMenu(LocalizedText title) : base(title) { ((ScrollingMenuScreen)this).Content.VerticalSpacing = 60f; GenerateMainPage(); thisSettingMenu = this; UpdateAllSubMenuColors(); } private void GenerateMainPage() { ConfigFile configFile = Settings.ConfigFile; Dictionary<string, Dictionary<string, ConfigEntryBase>> dictionary = new Dictionary<string, Dictionary<string, ConfigEntryBase>>(); foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in configFile) { if (!dictionary.TryGetValue(item.Key.Section, out var value)) { dictionary[item.Key.Section] = new Dictionary<string, ConfigEntryBase> { { item.Key.Key, item.Value } }; } else { value.Add(item.Key.Key, item.Value); } } foreach (KeyValuePair<string, Dictionary<string, ConfigEntryBase>> item2 in dictionary) { if (item2.Value.Count == 1) { KeyValuePair<string, ConfigEntryBase> keyValuePair = item2.Value.First(); Label(item2.Key, (FontSizes)1); ElementBuilder(keyValuePair.Value); continue; } SmolRandomizerMenuBuilder screenBuilder = (SmolRandomizerMenuBuilder)(object)SmolRandomizerMenuBuilder.BuildPagedSubMenu(item2); Additional_Elements(ref screenBuilder, item2); randoMenuButtons.Add(SubMenuButton((AbstractMenuScreen)(object)screenBuilder, CuteRandoCore.GetRandoDescription(item2.Key), (FontSizes)1)); if (!(item2.Key == "Main Settings")) { continue; } TextButton saveInfo = SubMenuButton((AbstractMenuScreen)(object)SaveInfoScreen(), "Information for the current save.", (FontSizes)1); ((MenuElement)saveInfo).OnVisibilityChanged += delegate(bool visible) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (visible) { ((MenuElement)saveInfo).SetMainColor(Settings.Loaded ? Color.white : Color.gray); } }; randoMenuButtons.Add(saveInfo); } } private static void Additional_Elements(ref SmolRandomizerMenuBuilder screenBuilder, KeyValuePair<string, Dictionary<string, ConfigEntryBase>> settingGroup) { string key = settingGroup.Key; Dictionary<string, ConfigEntryBase> settings = settingGroup.Value; if (!key.Equals("Main Settings")) { screenBuilder.Button("Defaults", delegate { foreach (ConfigEntryBase value in settings.Values) { value.BoxedValue = value.DefaultValue; } }, "Resets the settings to their default values.", (FontSizes)1); screenBuilder.BlankSpace(); return; } screenBuilder.Button("Reset All Settings to Their Defaults", delegate { try { foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in Settings.ConfigFile) { if (item.Key.Section != "Main Settings") { item.Value.BoxedValue = item.Value.DefaultValue; } } } catch (Exception ex) { Console.Error.WriteLineAsync("[Smol Randomizer] Exception encountered when resetting all settings.\n" + ex.Message); } }, "Resets the settings for all the randomizers to their default settings.", (FontSizes)1); screenBuilder.BlankSpace(); } private static void ResetAllSavedData() { try { HashSet<string> hashSet = new HashSet<string>(); foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in Settings.ConfigFile) { string section = item.Key.Section; if (!hashSet.Contains(item.Key.Section)) { SettingMenu.OnResetClicked?.Invoke(section); hashSet.Add(section); } } } catch (Exception ex) { Console.Error.WriteLineAsync("[Smol Randomizer] Exception encountered when resetting all saved values.\n" + ex.Message); } } private static SmolRandomizerMenuBuilder SaveInfoScreen() { SmolRandomizerMenuBuilder smolRandomizerMenuBuilder = new SmolRandomizerMenuBuilder(LocalizedText.op_Implicit("Current Save Information")); TextLabel seedLabel = smolRandomizerMenuBuilder.Label(SeedText(), (FontSizes)1); ((MenuElement)seedLabel).OnVisibilityChanged += delegate(bool visible) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (visible) { seedLabel.Text.text = SeedText(); ((MenuElement)seedLabel).SetMainColor(Settings.Loaded ? Color.white : Color.gray); } }; TextInput<int> seedInput = SeedInput("Set Seed", "Sets the seed to the entered value.", seedLabel); TextButton seedButton = smolRandomizerMenuBuilder.Button("Reroll Seed", delegate { if (Settings.Loaded) { Settings.SaveData.RerollSeed(); seedLabel.Text.text = SeedText(); ((SelectableValueElement<int>)(object)seedInput).Model.SetValue(Settings.SaveData.SaveSeed); } }, "", (FontSizes)1); ((MenuElement)seedButton).OnVisibilityChanged += delegate(bool visible) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (visible) { ((MenuElement)seedButton).SetMainColor(Settings.Loaded ? Color.white : Color.gray); } }; ((ScrollingMenuScreen)smolRandomizerMenuBuilder).Add((MenuElement)(object)seedInput); return smolRandomizerMenuBuilder; static TextInput<int> SeedInput(string label, string description, TextLabel val2) { ParserTextModel<int> val = TextModels.ForIntegers(); TextInput<int> intInput = new TextInput<int>(LocalizedText.op_Implicit(label), (ITextModel<int>)(object)val, LocalizedText.op_Implicit(description)) { Value = (Settings.Loaded ? Settings.SaveData.SaveSeed : 0) }; ((SelectableValueElement<int>)(object)intInput).OnValueChanged += delegate(int value) { if (Settings.Loaded) { Settings.SaveData.SetSeed(value); val2.Text.text = SeedText(); ResetAllSavedData(); } }; ((MenuElement)intInput).OnVisibilityChanged += delegate(bool visible) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (visible) { ((SelectableValueElement<int>)(object)intInput).Value = (Settings.Loaded ? Settings.SaveData.SaveSeed : 0); ((MenuElement)intInput).SetMainColor(Settings.Loaded ? Color.white : Color.gray); } }; return intInput; } static string SeedText() { if (!Settings.Loaded) { return "No Save Loaded"; } return "Seed: " + Settings.SaveData.SaveSeed; } } internal static void OnRandomizerEnable(object sender, EventArgs args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) UpdateSubMenuColor(((SettingChangedEventArgs)args).ChangedSetting); } internal static void UpdateSubMenuColor(ConfigEntryBase entry) { bool flag; switch (entry.BoxedValue.ToString().ToLower()) { case "none": case "disabled": case "false": flag = true; break; default: flag = false; break; } bool flag2 = flag; preInitSetting[entry.Definition.Section] = flag2; if (thisSettingMenu != null) { thisSettingMenu?.UpdateSubMenuColor(entry.Definition.Section, flag2); } } internal void UpdateAllSubMenuColors() { foreach (KeyValuePair<string, bool> item in preInitSetting) { UpdateSubMenuColor(item.Key, item.Value); } } private void UpdateSubMenuColor(string entry, bool enabled) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) foreach (TextButton randoMenuButton in randoMenuButtons) { if (randoMenuButton.ButtonText.text.TrimEnd() == entry) { if (enabled) { ((MenuElement)randoMenuButton).SetMainColor(SmolRandomizerMenuBuilder.Disabled); } else { ((MenuElement)randoMenuButton).SetMainColor(SmolRandomizerMenuBuilder.Enabled); } } } } internal static void OnEnabledRandomizerColorChanged(object sender, EventArgs args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) ChangeColors((RandomizerColors)((SettingChangedEventArgs)args).ChangedSetting.BoxedValue); } internal static void ChangeColors(RandomizerColors newColor) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (CuteRandoCore.randomize) { switch (newColor) { case RandomizerColors.GreenRed: SmolRandomizerMenuBuilder.Enabled = Color.green; SmolRandomizerMenuBuilder.Disabled = Color.red; break; case RandomizerColors.BlueYellow: SmolRandomizerMenuBuilder.Enabled = SmolRandomizerMenuBuilder.EBlue; SmolRandomizerMenuBuilder.Disabled = SmolRandomizerMenuBuilder.DYellow; break; case RandomizerColors.PurpleOrange: SmolRandomizerMenuBuilder.Enabled = SmolRandomizerMenuBuilder.EPurple; SmolRandomizerMenuBuilder.Disabled = SmolRandomizerMenuBuilder.DOrange; break; default: throw new NotImplementedException(); } } else { SmolRandomizerMenuBuilder.Enabled = SmolRandomizerMenuBuilder.LightGray; SmolRandomizerMenuBuilder.Disabled = SmolRandomizerMenuBuilder.LightGray; } thisSettingMenu?.UpdateAllSubMenuColors(); } } public static class Settings { public enum RangeType { Percent, Value } internal static ConfigEntry<bool> enableRandomizer; public static readonly bool defaultEnableRandomizer = true; private static ConfigEntry<RandomizerColors> enabledRandomizerColors; public static readonly RandomizerColors defaultEnabledRandomizerColors = RandomizerColors.GreenRed; public static readonly int maxSliderPercent = 300; public static readonly int maxSliderValue = 100; private static readonly TypeConverter FloatRangeConverter = new TypeConverter { ConvertToString = (object obj, Type type) => obj.ToString(), ConvertToObject = (string str, Type type) => FloatRange.Parse(str) }; private static readonly TypeConverter IntRangeConverter = new TypeConverter { ConvertToString = (object obj, Type type) => obj.ToString(), ConvertToObject = (string str, Type type) => IntRange.Parse(str) }; private static RandoPerSaveData saveData; private static bool loaded = false; internal static bool loading = false; public static bool EnableRandomizer { get { return enableRandomizer.Value; } internal set { enableRandomizer.Value = value; } } public static RandomizerColors EnabledRandomizerColors { get { return enabledRandomizerColors.Value; } internal set { enabledRandomizerColors.Value = value; } } public static ConfigFile ConfigFile { get; private set; } public static RandoPerSaveData SaveData { get { if (saveData == null) { if (saveData == null) { saveData = new RandoPerSaveData(); } RandoPerSaveData.Saving(); } return saveData; } set { saveData = value; saveData.Load(); } } public static bool Loaded { get { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (loading) { if ((int)GameManager.instance.sm.sceneType == 0) { loaded = true; } else { loaded = false; } loading = false; } return loaded; } } public static void Init(ConfigFile config) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown ConfigFile = config; TomlTypeConverter.AddConverter(typeof(FloatRange), FloatRangeConverter); TomlTypeConverter.AddConverter(typeof(IntRange), IntRangeConverter); enableRandomizer = config.Bind<bool>("Main Settings", "Enable Randomizer", defaultEnableRandomizer, new ConfigDescription("Enable Randomization.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 1 } })); enabledRandomizerColors = config.Bind<RandomizerColors>("Main Settings", "Enabled/Disabled Colors", defaultEnabledRandomizerColors, new ConfigDescription("Changes the colors of the enabled/disabled randomizers.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 3 } })); enableRandomizer.SettingChanged += CuteRandoCore.UpdateSettings; enabledRandomizerColors.SettingChanged += SettingMenu.OnEnabledRandomizerColorChanged; SettingMenu.ChangeColors(EnabledRandomizerColors); } public static void RangeDrawer(ConfigEntryBase entry) { Type settingType = entry.SettingType; if (settingType == typeof(FloatRange)) { FloatRange obj = (FloatRange)entry.BoxedValue; string min = (obj.Min * 100f).ToString(); string max = (obj.Max * 100f).ToString(); TextRange(ref min, ref max, RangeType.Percent, entry.Description.AcceptableValues); try { entry.BoxedValue = new FloatRange(float.Parse(min) / 100f, float.Parse(max) / 100f); return; } catch (ArgumentException ex) { Console.Error.WriteLine(ex.Message); return; } } if (settingType == typeof(IntRange)) { IntRange obj2 = (IntRange)entry.BoxedValue; string min2 = obj2.Min.ToString(); string max2 = obj2.Max.ToString(); TextRange(ref min2, ref max2, RangeType.Value, entry.Description.AcceptableValues); try { entry.BoxedValue = checked(new IntRange((int)Math.Round(float.Parse(min2)), (int)Math.Round(float.Parse(max2)))); return; } catch (ArgumentException ex2) { Console.Error.WriteLine(ex2.Message); return; } } Console.Error.WriteLine("Unimplimented entryType"); } private static void TextRange(ref string min, ref string max, RangeType rangeType, AcceptableValueBase? acceptableRange = null) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown int num = 0; int num2 = (rangeType.Equals(RangeType.Percent) ? maxSliderPercent : maxSliderValue); checked { if (acceptableRange is AcceptableRangeforIntRange acceptableRangeforIntRange) { num = acceptableRangeforIntRange.MinValue; num2 = acceptableRangeforIntRange.MaxValue; } else if (acceptableRange is AcceptableRangeforFloatRange acceptableRangeforFloatRange) { num = (int)acceptableRangeforFloatRange.MinValue; num2 = (int)acceptableRangeforFloatRange.MaxValue; } VerticalScope val = new VerticalScope(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>()); try { HorizontalScope val2 = new HorizontalScope(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>()); try { GUILayout.Label("Minimum " + (rangeType.Equals(RangeType.Percent) ? "Percent" : "Value"), Array.Empty<GUILayoutOption>()); min = GUILayout.TextField(min, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) }); min = GUILayout.HorizontalSlider((float)Math.Round(float.Parse(min)), (float)num, (float)Math.Round(float.Parse(max)), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }).ToString(); } finally { ((IDisposable)val2)?.Dispose(); } HorizontalScope val3 = new HorizontalScope(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>()); try { GUILayout.Label("Maximum " + (rangeType.Equals(RangeType.Percent) ? "Percent" : "Value"), Array.Empty<GUILayoutOption>()); max = GUILayout.TextField(max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) }); max = GUILayout.HorizontalSlider((float)Math.Round(float.Parse(max)), (float)Math.Round(float.Parse(min)), (float)num2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }).ToString(); } finally { ((IDisposable)val3)?.Dispose(); } } finally { ((IDisposable)val)?.Dispose(); } } } } public class RandoPerSaveData { [JsonProperty] private int saveSeed = int.MinValue; [JsonIgnore] public int SaveSeed { get { if (saveSeed == int.MinValue) { saveSeed = CuteRandoCore.GetNewSaveSeed(); } return saveSeed; } } internal static event Action<bool> OnSettingsLoaded; internal static event Action OnSettingsSaved; internal void Load() { Settings.loading = true; } internal static void Saving() { RandoPerSaveData.OnSettingsSaved?.Invoke(); } internal void RerollSeed() { saveSeed = CuteRandoCore.GetNewSaveSeed(); } internal void SetSeed(int seed) { saveSeed = seed; } } public enum RandomizeByRangeTypes { Disabled, Percent, Value } internal enum RandomizeByFlatAmount { Disabled, Shift, Range } public enum RandomizerConsistencyA { None, Scene, EnemyType } public enum RandomizerConsistencyB { None, Scene, PerSave } [Flags] public enum RandomizerEnemyTypeFlags { None = 0, Enemy = 1, Boss = 2, Both = 3 } public enum RandomizerColors { GreenRed, BlueYellow, PurpleOrange } public class SmolRandomizerMenuBuilder : ScrollingMenuScreen { public const float VSPACE_TIGHT = 60f; public static Color LightGray => new Color(0.75f, 0.75f, 0.75f); public static Color EBlue => RGBInttoColor(12, 123, 220); public static Color DYellow => RGBInttoColor(255, 194, 10); public static Color EPurple => RGBInttoColor(151, 93, 255); public static Color DOrange => RGBInttoColor(230, 97, 0); public static Color Enabled { get; internal set; } public static Color Disabled { get; internal set; } public SmolRandomizerMenuBuilder(LocalizedText title) : base(title) { } private static Color RGBInttoColor(int r, int g, int b, int a = 255) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) return new Color((float)clamp(r) / 255f, (float)clamp(g) / 255f, (float)clamp(b) / 255f, (float)clamp(a) / 255f); static int clamp(int val) { if (val > 255) { val = 255; } if (val < 0) { val = 0; } return val; } } public TextLabel BlankSpace() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown TextLabel val = new TextLabel(LocalizedText.op_Implicit("")); ((ScrollingMenuScreen)this).Add((MenuElement)(object)val); return val; } public TextLabel Label(string label, FontSizes fontSize = (FontSizes)1) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Label(label, Color.white, fontSize); } public TextLabel Label(string label, Color color, FontSizes fontSize = (FontSizes)1) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) TextLabel val = new TextLabel(LocalizedText.op_Implicit(label)); ((MenuElement)val).SetFontSizes(fontSize); ((MenuElement)val).SetMainColor(color); val.Text.horizontalOverflow = (HorizontalWrapMode)1; ((ScrollingMenuScreen)this).Add((MenuElement)(object)val); return val; } public TextButton Button(string label, Action onClick, string description = "", FontSizes fontSize = (FontSizes)1) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) TextButton val = new TextButton(LocalizedText.op_Implicit(label), LocalizedText.op_Implicit(description)); ((MenuElement)val).SetFontSizes(fontSize); val.OnSubmit = (Action)Delegate.Combine(val.OnSubmit, onClick); val.DescriptionText.horizontalOverflow = (HorizontalWrapMode)1; ((ScrollingMenuScreen)this).Add((MenuElement)(object)val); return val; } public TextButton SubMenuButton(AbstractMenuScreen subMenu, string description = "", FontSizes fontSize = (FontSizes)1) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0008: Unknown result type (might be due to invalid IL or missing references) TextButton val = new TextButton(subMenu); ((MenuElement)val).SetFontSizes(fontSize); LocalizedTextExtensions[val.DescriptionText] = LocalizedText.op_Implicit(description); val.DescriptionText.horizontalOverflow = (HorizontalWrapMode)1; ((ScrollingMenuScreen)this).Add((MenuElement)(object)val); BlankSpace(); return val; } public ChoiceElement<bool> ToggleElement(string label, ConfigEntryBase configEntry, string description = "", FontSizes fontSizes = (FontSizes)1) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) ChoiceElement<bool> val = new ChoiceElement<bool>(LocalizedText.op_Implicit(label), (IChoiceModel<bool>)(object)ChoiceModels.ForBool(), LocalizedText.op_Implicit(description)); ConfigEntryFactoryExtensions.SynchronizeRawWith((BaseSelectableValueElement)(object)val, configEntry); ((MenuElement)val).SetFontSizes(fontSizes); val.DescriptionText.horizontalOverflow = (HorizontalWrapMode)1; ((ScrollingMenuScreen)this).Add((MenuElement)(object)val); return val; } public object? EnumList(ConfigEntryBase configEntry, FontSizes fontSizes = (FontSizes)1) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) MenuElement val = default(MenuElement); if (!ConfigEntryFactory.GenerateEnumChoiceElement(configEntry, ref val) || val == null) { string text = "Failed Generation"; if (val == null) { text = "Null Element"; } Label("(" + text + ")" + ConfigEntryFactoryExtensions.LabelName(configEntry), Color.magenta, (FontSizes)1); return null; } val.SetFontSizes(fontSizes); ((ChoiceElement<object>)(object)val).DescriptionText.horizontalOverflow = (HorizontalWrapMode)1; ((ScrollingMenuScreen)this).Add(val); return val; } public SliderElement<float>[] SliderRangeFloat(string label, ConfigEntryBase configEntry, string description = "") { //IL_0018: Unknown result type (might be due to invalid IL or missing references) Label(label, (FontSizes)1); if (description != "") { Label(description, LightGray, (FontSizes)0).Text.horizontalOverflow = (HorizontalWrapMode)1; } float item; float item2; float num; float num2; if (!(configEntry.Description.AcceptableValues is AcceptableRangeforFloatRange acceptableRangeforFloatRange)) { Tuple.Create(0f, (float)Settings.maxSliderPercent).Deconstruct(out item, out item2); num = item; num2 = item2; } else { Tuple.Create(acceptableRangeforFloatRange.MinValue * 100f, acceptableRangeforFloatRange.MaxValue * 100f).Deconstruct(out item2, out item); num = item2; num2 = item; } int num3 = checked((int)Math.Round(num2 - num + 1f)); LinearFloatSliderModel val = SliderModels.ForFloats(num, num2, num3); ((SliderModel<float>)(object)val).DisplayFn = SliderCuteExtensions.AsPercent; LinearFloatSliderModel val2 = SliderModels.ForFloats(num, num2, num3); ((SliderModel<float>)(object)val2).DisplayFn = SliderCuteExtensions.AsPercent; SliderElement<float> val3 = new SliderElement<float>(LocalizedText.op_Implicit("Minimum Percent"), (SliderModel<float>)(object)val); ((MenuElement)val3).SetFontSizes((FontSizes)0); ((SelectableValueElement<float>)(object)val3).SynchronizeWithFloatRangeMin(configEntry); val3.ValueText.horizontalOverflow = (HorizontalWrapMode)1; ((ScrollingMenuScreen)this).Add((MenuElement)(object)val3); SliderElement<float> val4 = new SliderElement<float>(LocalizedText.op_Implicit("Maximum Percent"), (SliderModel<float>)(object)val2); ((MenuElement)val4).SetFontSizes((FontSizes)0); ((SelectableValueElement<float>)(object)val4).SynchronizeWithFloatRangeMax(configEntry); val4.ValueText.horizontalOverflow = (HorizontalWrapMode)1; ((ScrollingMenuScreen)this).Add((MenuElement)(object)val4); return new SliderElement<float>[2] { val3, val4 }; } public SliderElement<int>[] SliderRangeInt(string label, ConfigEntryBase configEntry, string description = "") { //IL_0018: Unknown result type (might be due to invalid IL or missing references) Label(label, (FontSizes)1); if (description != "") { Label(description, LightGray, (FontSizes)0).Text.horizontalOverflow = (HorizontalWrapMode)1; } int item; int item2; int num; int num2; if (!(configEntry.Description.AcceptableValues is AcceptableRangeforIntRange acceptableRangeforIntRange)) { Tuple.Create(0, Settings.maxSliderPercent).Deconstruct(out item, out item2); num = item; num2 = item2; } else { Tuple.Create(acceptableRangeforIntRange.MinValue, acceptableRangeforIntRange.MaxValue).Deconstruct(out item2, out item); num = item2; num2 = item; } IntSliderModel val = SliderModels.ForInts(num, num2); IntSliderModel val2 = SliderModels.ForInts(num, num2); SliderElement<int> val3 = new SliderElement<int>(LocalizedText.op_Implicit("Minimum Value"), (SliderModel<int>)(object)val); ((MenuElement)val3).SetFontSizes((FontSizes)0); ((SelectableValueElement<int>)(object)val3).SynchronizeWithIntRangeMin(configEntry); val3.ValueText.horizontalOverflow = (HorizontalWrapMode)1; ((ScrollingMenuScreen)this).Add((MenuElement)(object)val3); SliderElement<int> val4 = new SliderElement<int>(LocalizedText.op_Implicit("Maximum Value"), (SliderModel<int>)(object)val2); ((MenuElement)val4).SetFontSizes((FontSizes)0); ((SelectableValueElement<int>)(object)val4).SynchronizeWithIntRangeMax(configEntry); val4.ValueText.horizontalOverflow = (HorizontalWrapMode)1; ((ScrollingMenuScreen)this).Add((MenuElement)(object)val4); return new SliderElement<int>[2] { val3, val4 }; } public TextInput<int> IntInput(string label, ConfigEntryBase configEntry, string description = "") { ParserTextModel<int> val = ((configEntry.Description.AcceptableValues is AcceptableValueRange<int> val2) ? TextModels.ForIntegers(val2.MinValue, val2.MaxValue) : TextModels.ForIntegers()); TextInput<int> val3 = new TextInput<int>(LocalizedText.op_Implicit(label), (ITextModel<int>)(object)val, LocalizedText.op_Implicit(description)); ConfigEntryFactoryExtensions.SynchronizeRawWith((BaseSelectableValueElement)(object)val3, configEntry); ((SelectableValueElement<int>)(object)val3).Model.SetValue((int)configEntry.BoxedValue); val3.DescriptionText.horizontalOverflow = (HorizontalWrapMode)1; ((ScrollingMenuScreen)this).Add((MenuElement)(object)val3); return val3; } public SliderElement<int> IntSlider(string label, ConfigEntryBase configEntry, string description = "") { //IL_0087: Unknown result type (might be due to invalid IL or missing references) int num; int num2; if (configEntry.Description.AcceptableValues is AcceptableValueRange<int> range) { (num, num2) = SliderCuteExtensions.RangeAsTuple(range); } else { int maxSliderValue = Settings.maxSliderValue; num2 = maxSliderValue; num = 0; } IntSliderModel val = SliderModels.ForInts(num, num2); SliderElement<int> val2 = new SliderElement<int>(LocalizedText.op_Implicit(label), (SliderModel<int>)(object)val); ConfigEntryFactoryExtensions.SynchronizeRawWith((BaseSelectableValueElement)(object)val2, configEntry); ((SelectableValueElement<int>)(object)val2).Model.SetValue((int)configEntry.BoxedValue); ((ScrollingMenuScreen)this).Add((MenuElement)(object)val2); if (description != "") { Label(description, LightGray, (FontSizes)0).Text.horizontalOverflow = (HorizontalWrapMode)1; } return val2; } public static ScrollingMenuScreen BuildPagedSubMenu(KeyValuePair<string, Dictionary<string, ConfigEntryBase>> settingGroup) { string key = settingGroup.Key; Dictionary<string, ConfigEntryBase> value = settingGroup.Value; SmolRandomizerMenuBuilder smolRandomizerMenuBuilder = new SmolRandomizerMenuBuilder(LocalizedText.op_Implicit(key)); ((ScrollingMenuScreen)smolRandomizerMenuBuilder).Content.VerticalSpacing = 60f; foreach (ConfigEntryBase value2 in value.Values) { smolRandomizerMenuBuilder.ElementBuilder(value2); } return (ScrollingMenuScreen)(object)smolRandomizerMenuBuilder; } public void ElementBuilder(ConfigEntryBase entry) { //IL_0153: Unknown result type (might be due to invalid IL or missing references) switch (entry.SettingType.IsEnum ? "Enum" : entry.SettingType.Name) { case "Boolean": ToggleElement(ConfigEntryFactoryExtensions.LabelName(entry), entry, entry.Description.Description, (FontSizes)1); if (entry.Description.Description != "") { BlankSpace(); } break; case "Int32": IntSlider(ConfigEntryFactoryExtensions.LabelName(entry), entry, entry.Description.Description); if (entry.Description.Description != "") { BlankSpace(); } break; case "FloatRange": SliderRangeFloat(ConfigEntryFactoryExtensions.LabelName(entry), entry, entry.Description.Description); break; case "IntRange": SliderRangeInt(ConfigEntryFactoryExtensions.LabelName(entry), entry, entry.Description.Description); break; case "Enum": EnumList(entry, (FontSizes)1); if (entry.Description.Description != "") { BlankSpace(); } break; default: Label("(Unimplemented)" + ConfigEntryFactoryExtensions.LabelName(entry), Color.magenta, (FontSizes)1); break; } } } public static class SliderCuteExtensions { public static LocalizedText AsPercent(int _, float item) { return LocalizedText.op_Implicit($"{item:0.###}%"); } public static (int min, int max) RangeAsTuple(AcceptableValueRange<int> range) { return (min: range.MinValue, max: range.MaxValue); } public static void SynchronizeWithFloatRangeMin(this SelectableValueElement<float> element, ConfigEntryBase entry) { ConfigEntry<FloatRange> configEntry = (entry as ConfigEntry<FloatRange>) ?? throw new ArgumentException("Parameter entry was not a FloatRange"); IValueModel<float> model = element.Model; model.SetValue(configEntry.Value.Min * 100f); model.OnValueChanged += delegate(float value) { value /= 100f; if (value > configEntry.Value.Max) { value = configEntry.Value.Max; model.SetValue(value * 100f); } ((ConfigEntryBase)configEntry).BoxedValue = new FloatRange(value, configEntry.Value.Max); }; ((MenuElement)element).OnVisibilityChanged += delegate(bool visible) { if (visible) { model.SetValue(configEntry.Value.Min * 100f); } }; configEntry.SettingChanged += handler; ((MenuDisposable)element).OnDispose += delegate { configEntry.SettingChanged -= handler; }; void handler(object _, EventArgs args) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) model.SetValue(((FloatRange)((SettingChangedEventArgs)args).ChangedSetting.BoxedValue).Min * 100f); } } public static void SynchronizeWithFloatRangeMax(this SelectableValueElement<float> element, ConfigEntryBase entry) { ConfigEntry<FloatRange> configEntry = (entry as ConfigEntry<FloatRange>) ?? throw new ArgumentException("Parameter entry was not a FloatRange"); IValueModel<float> model = element.Model; model.SetValue(configEntry.Value.Max * 100f); model.OnValueChanged += delegate(float value) { value /= 100f; if (value < configEntry.Value.Min) { value = configEntry.Value.Min; model.SetValue(value * 100f); } ((ConfigEntryBase)configEntry).BoxedValue = new FloatRange(configEntry.Value.Min, value); }; ((MenuElement)element).OnVisibilityChanged += delegate(bool visible) { if (visible) { model.SetValue(configEntry.Value.Max * 100f); } }; configEntry.SettingChanged += handler; ((MenuDisposable)element).OnDispose += delegate { configEntry.SettingChanged -= handler; }; void handler(object _, EventArgs args) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) model.SetValue(((FloatRange)((SettingChangedEventArgs)args).ChangedSetting.BoxedValue).Max * 100f); } } public static void SynchronizeWithIntRangeMin(this SelectableValueElement<int> element, ConfigEntryBase entry) { ConfigEntry<IntRange> configEntry = (entry as ConfigEntry<IntRange>) ?? throw new ArgumentException("Parameter entry was not an IntRange"); IValueModel<int> model = element.Model; model.SetValue(configEntry.Value.Min); model.OnValueChanged += delegate(int value) { if (value > configEntry.Value.Max) { value = configEntry.Value.Max; model.SetValue(value); } ((ConfigEntryBase)configEntry).BoxedValue = new IntRange(value, configEntry.Value.Max); }; ((MenuElement)element).OnVisibilityChanged += delegate(bool visible) { if (visible) { model.SetValue(configEntry.Value.Min); } }; configEntry.SettingChanged += handler; ((MenuDisposable)element).OnDispose += delegate { configEntry.SettingChanged -= handler; }; void handler(object _, EventArgs args) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) model.SetValue(((IntRange)((SettingChangedEventArgs)args).ChangedSetting.BoxedValue).Min); } } public static void SynchronizeWithIntRangeMax(this SelectableValueElement<int> element, ConfigEntryBase entry) { ConfigEntry<IntRange> configEntry = (entry as ConfigEntry<IntRange>) ?? throw new ArgumentException("Parameter entry was not an IntRange"); IValueModel<int> model = element.Model; model.SetValue(configEntry.Value.Max); model.OnValueChanged += delegate(int value) { if (value < configEntry.Value.Min) { value = configEntry.Value.Min; model.SetValue(value); } ((ConfigEntryBase)configEntry).BoxedValue = new IntRange(configEntry.Value.Min, value); }; ((MenuElement)element).OnVisibilityChanged += delegate(bool visible) { if (visible) { model.SetValue(configEntry.Value.Max); } }; configEntry.SettingChanged += handler; ((MenuDisposable)element).OnDispose += delegate { configEntry.SettingChanged -= handler; }; void handler(object _, EventArgs args) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) model.SetValue(((IntRange)((SettingChangedEventArgs)args).ChangedSetting.BoxedValue).Max); } } } } namespace Smol_Randomizer.Randomizers { internal class Enemy_Currency_Rando : Rando_Base { private static readonly Lazy<Enemy_Currency_Rando> instance = new Lazy<Enemy_Currency_Rando>(() => new Enemy_Currency_Rando()); private readonly HashSet<HealthManager> currentEnemyHealthManagers = new HashSet<HealthManager>(); private readonly Dictionary<string, RandomizedGeoSet> enemyGeoSets = new Dictionary<string, RandomizedGeoSet>(); private readonly Dictionary<string, Dictionary<string, RandomizedGeoSet>> sceneGeoSets = new Dictionary<string, Dictionary<string, RandomizedGeoSet>>(); private readonly Dictionary<string, int> enemyShards = new Dictionary<string, int>(); private readonly Dictionary<string, Dictionary<string, int>> sceneShards = new Dictionary<string, Dictionary<string, int>>(); internal static int smallGeoValue = 0; internal static int mediumGeoValue = 0; internal static int largeGeoValue = 0; private Randomizer_Info eventActiveEnemy; private Randomizer_Info eventOnFirstSceneFrame; private ConfigEntry<RandomizerConsistencyA> randomizerConsistency; public readonly RandomizerConsistencyA defaultRandomizerConsistency; private ConfigEntry<RandomizeByRangeTypes> rosaryRandomizerType; public readonly RandomizeByRangeTypes defaultRosaryRandomizerType; private ConfigEntry<FloatRange> rosaryPercentDropRange; public readonly FloatRange defaultRosaryPercentDropRange = new FloatRange(0.5f, 2f); private ConfigEntry<IntRange> rosaryValueDropRange; public readonly IntRange defaultRosaryValueDropRange = new IntRange(0, 15); private ConfigEntry<RandomizeByRangeTypes> shardRandomizerType; public readonly RandomizeByRangeTypes defaultShardRandomizerType; private ConfigEntry<FloatRange> shardPercentDropRange; public readonly FloatRange defaultShardPercentDropRange = new FloatRange(0.5f, 2f); private ConfigEntry<IntRange> shardValueDropRange; public readonly IntRange defaultShardValueDropRange = new IntRange(0, 15); private RandomizeByRangeTypes currentRosarySetting; private RandomizeByRangeTypes currentShardSetting; public static Enemy_Currency_Rando Instance => instance.Value; public RandomizerConsistencyA RandomizerConsistency { get { return randomizerConsistency.Value; } internal set { randomizerConsistency.Value = value; } } public RandomizeByRangeTypes RosaryRandomizerType { get { return rosaryRandomizerType.Value; } internal set { rosaryRandomizerType.Value = value; } } public FloatRange RosaryPercentDropRange { get { return rosaryPercentDropRange.Value; } internal set { rosaryPercentDropRange.Value = value; } } public IntRange RosaryValueDropRange { get { return rosaryValueDropRange.Value; } internal set { rosaryValueDropRange.Value = value; } } public RandomizeByRangeTypes ShardRandomizerType { get { return shardRandomizerType.Value; } internal set { shardRandomizerType.Value = value; } } public FloatRange ShardPercentDropRange { get { return shardPercentDropRange.Value; } internal set { shardPercentDropRange.Value = value; } } public IntRange ShardValueDropRange { get { return shardValueDropRange.Value; } internal set { shardValueDropRange.Value = value; } } private Enemy_Currency_Rando() { InitRandomizer(); } private protected override void InitRandomizer() { RandomizerName = "Enemy Currency Randomizer"; RandomizerDescription = "Randomizes the quantity of Rosaries and Shards dropped by enemies."; if (CuteRandoCore.RegisterRandomizer(new Randomizer_Info(RandomizerName, RandomizerEventType.GameStartup, AccessTools.Method(typeof(Enemy_Currency_Rando), "GameStartup", (Type[])null, (Type[])null), this))) { eventActiveEnemy = new Randomizer_Info(RandomizerName, RandomizerEventType.ActiveEnemy, AccessTools.Method(typeof(Enemy_Currency_Rando), "SetCurrency", (Type[])null, (Type[])null), this); eventOnFirstSceneFrame = new Randomizer_Info(RandomizerName, RandomizerEventType.OnFirstSceneFrame, AccessTools.Method(typeof(Enemy_Currency_Rando), "OnFirstSceneFrame", (Type[])null, (Type[])null), this); smallGeoValue = ((IntReference)Gameplay.SmallGeoValue).Value; mediumGeoValue = ((IntReference)Gameplay.MediumGeoValue).Value; largeGeoValue = ((IntReference)Gameplay.LargeGeoValue).Value; base.InitRandomizer(); } } private protected override void Register() { CuteRandoCore.RegisterRandomizer(eventActiveEnemy); CuteRandoCore.RegisterRandomizer(eventOnFirstSceneFrame); } private protected override void Unregister() { CuteRandoCore.UnregisterRandomizer(eventActiveEnemy); CuteRandoCore.UnregisterRandomizer(eventOnFirstSceneFrame); } private void GameStartup() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown CuteRandoCore.harmony.Patch((MethodBase)AccessTools.Method(typeof(HealthManager), "OnEnable", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Enemy_Currency_Rando), "HealthManagerOnEnablePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private void OnFirstSceneFrame() { currentEnemyHealthManagers.RemoveWhere((HealthManager x) => (Object)(object)x == (Object)null); } private static void HealthManagerOnEnablePostfix(ref HealthManager __instance, ref int ___smallGeoDrops, ref int ___mediumGeoDrops, ref int ___largeGeoDrops, ref int ___shellShardDrops) { if (Instance.coreEnableRandomization && Instance.currentEnemyHealthManagers.Add(__instance)) { Instance.SetCurrency(__instance, ref ___smallGeoDrops, ref ___mediumGeoDrops, ref ___largeGeoDrops, ref ___shellShardDrops); } } private void SetCurrency(HealthManager thing, ref int smallGeoDrops, ref int mediumGeoDrops, ref int largeGeoDrops, ref int shellShardDrops) { if (!((Object)(object)thing == (Object)null)) { if (RosaryRandomizerType != RandomizeByRangeTypes.Disabled) { RandomizeGeo(thing, out RandomizedGeoSet geoSet); smallGeoDrops = geoSet.SmallGeo; mediumGeoDrops = geoSet.MediumGeo; largeGeoDrops = geoSet.LargeGeo; } if (ShardRandomizerType != RandomizeByRangeTypes.Disabled) { RandomizeShards(thing, ref shellShardDrops); } } } private void RandomizeShards(HealthManager thing, ref int shellShardDrops) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Scene scene = ((Component)thing).gameObject.scene; string name = ((Scene)(ref scene)).name; string text = ((Object)thing).name; int num = checked(text.IndexOf('(') - 1); if (num > 0) { text = text.Substring(0, num); } int value2; switch (RandomizerConsistency) { case RandomizerConsistencyA.EnemyType: if (!enemyShards.TryGetValue(text, out value2)) { value2 = GetRandoTypeShards(shellShardDrops, CuteRandoCore.RNGSeed(text)); enemyShards[text] = value2; } shellShardDrops = value2; break; case RandomizerConsistencyA.Scene: { if (!sceneShards.TryGetValue(name, out Dictionary<string, int> value)) { value2 = GetRandoTypeShards(shellShardDrops, CuteRandoCore.RNGSeed(text + name)); sceneShards[name] = new Dictionary<string, int> { { text, value2 } }; } else if (!value.TryGetValue(text, out value2)) { value2 = (value[text] = GetRandoTypeShards(shellShardDrops, CuteRandoCore.RNGSeed(text + name))); } shellShardDrops = value2; break; } case RandomizerConsistencyA.None: shellShardDrops = GetRandoTypeShards(shellShardDrops); break; default: throw new NotImplementedException(); } int GetRandoTypeShards(int num3, int seed = int.MinValue) { int result = 0; if (ShardRandomizerType == RandomizeByRangeTypes.Percent) { result = checked((int)Math.Round(CuteRandoCore.RandoHelper(ShardPercentDropRange.AsTuple(), seed) * (float)num3)); } else if (ShardRandomizerType == RandomizeByRangeTypes.Value) { result = CuteRandoCore.RandoHelper(ShardValueDropRange.AsTuple(), seed); } return result; } } private void RandomizeGeo(HealthManager thing, out RandomizedGeoSet geoSet) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) string text = ((Object)thing).name; int num = checked(text.IndexOf('(') - 1); if (num > 0) { text = text.Substring(0, num); } switch (RandomizerConsistency) { case RandomizerConsistencyA.EnemyType: if (!enemyGeoSets.TryGetValue(text, out geoSet)) { geoSet = GetRandoTypeGeo(thing, CuteRandoCore.RNGSeed(text)); enemyGeoSets[text] = geoSet; } break; case RandomizerConsistencyA.Scene: { Scene scene = ((Component)thing).gameObject.scene; string name = ((Scene)(ref scene)).name; if (!sceneGeoSets.TryGetValue(name, out Dictionary<string, RandomizedGeoSet> value)) { geoSet = GetRandoTypeGeo(thing, CuteRandoCore.RNGSeed(text + name)); sceneGeoSets[name] = new Dictionary<string, RandomizedGeoSet> { { text, geoSet } }; } else if (!value.TryGetValue(text, out geoSet)) { geoSet = GetRandoTypeGeo(thing, CuteRandoCore.RNGSeed(text + name)); value[text] = geoSet; } break; } case RandomizerConsistencyA.None: geoSet = GetRandoTypeGeo(thing); break; default: throw new NotImplementedException(); } RandomizedGeoSet GetRandoTypeGeo(HealthManager thing2, int seed = int.MinValue) { RandomizedGeoSet randomizedGeoSet = new RandomizedGeoSet(thing2); if (RosaryRandomizerType == RandomizeByRangeTypes.Percent) { randomizedGeoSet.MultiplyGeo(CuteRandoCore.RandoHelper(RosaryPercentDropRange.AsTuple(), seed)); } else if (RosaryRandomizerType == RandomizeByRangeTypes.Value) { randomizedGeoSet.SetGeoQuantity(CuteRandoCore.RandoHelper(RosaryValueDropRange.AsTuple(), seed)); } return randomizedGeoSet; } } private protected override void ResetAllLists() { currentEnemyHealthManagers.Clear(); enemyGeoSets.Clear(); enemyShards.Clear(); sceneGeoSets.Clear(); sceneShards.Clear(); } private protected override void InitSettings() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected O, but got Unknown ConfigFile configFile = Smol_Randomizer.Settings.Settings.ConfigFile; randomizerConsistency = configFile.Bind<RandomizerConsistencyA>(RandomizerName, "Currency Consistancy", defaultRandomizerConsistency, new ConfigDescription("Setting for if the drops should be consistent per enemy or room.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 6 } })); rosaryRandomizerType = configFile.Bind<RandomizeByRangeTypes>(RandomizerName, "Rosary Quantity", defaultRosaryRandomizerType, new ConfigDescription("Randomize rosary quantities dropped from enemies.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 5 } })); rosaryPercentDropRange = configFile.Bind<FloatRange>(RandomizerName, "Rosary Percent Drop Range", defaultRosaryPercentDropRange, new ConfigDescription("Randomize the rosary drops as a percentage.", (AcceptableValueBase)(object)new AcceptableRangeforFloatRange(0f, 3f), new object[1] { new ConfigurationManagerAttributes { Order = 4, CustomDrawer = Smol_Randomizer.Settings.Settings.RangeDrawer } })); rosaryValueDropRange = configFile.Bind<IntRange>(RandomizerName, "Rosary Value Drop Range", defaultRosaryValueDropRange, new ConfigDescription("Randomize the rosary drops as a flat amount.", (AcceptableValueBase)(object)new AcceptableRangeforIntRange(0, 100), new object[1] { new ConfigurationManagerAttributes { Order = 3, CustomDrawer = Smol_Randomizer.Settings.Settings.RangeDrawer } })); shardRandomizerType = configFile.Bind<RandomizeByRangeTypes>(RandomizerName, "Shard Quantity", defaultShardRandomizerType, new ConfigDescription("Randomize shard quantities dropped from enemies.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 2 } })); shardPercentDropRange = configFile.Bind<FloatRange>(RandomizerName, "Shard Percent Drop Range", defaultShardPercentDropRange, new ConfigDescription("Randomize the shard drops as a percentage.", (AcceptableValueBase)(object)new AcceptableRangeforFloatRange(0f, 3f), new object[1] { new ConfigurationManagerAttributes { Order = 1, CustomDrawer = Smol_Randomizer.Settings.Settings.RangeDrawer } })); shardValueDropRange = configFile.Bind<IntRange>(RandomizerName, "Shard Value Drop Range", defaultShardValueDropRange, new ConfigDescription("Randomize the shard drops as a flat amount.", (AcceptableValueBase)(object)new AcceptableRangeforIntRange(0, 50), new object[1] { new ConfigurationManagerAttributes { Order = 0, CustomDrawer = Smol_Randomizer.Settings.Settings.RangeDrawer } })); currentRosarySetting = rosaryRandomizerType.Value; currentShardSetting = shardRandomizerType.Value; rosaryRandomizerType.SettingChanged += OnRosarySettingsUpdated; rosaryPercentDropRange.SettingChanged += OnRosarySettingsUpdated; rosaryValueDropRange.SettingChanged += OnRosarySettingsUpdated; shardRandomizerType.SettingChanged += OnShardSettingsUpdated; shardPercentDropRange.SettingChanged += OnShardSettingsUpdated; shardValueDropRange.SettingChanged += OnShardSettingsUpdated; if (rosaryRandomizerType.Value.Equals(RandomizeByRangeTypes.Disabled) && shardRandomizerType.Value.Equals(RandomizeByRangeTypes.Disabled)) { SettingMenu.UpdateSubMenuColor((ConfigEntryBase)(object)rosaryRandomizerType); } else if (!rosaryRandomizerType.Value.Equals(RandomizeByRangeTypes.Disabled)) { SettingMenu.UpdateSubMenuColor((ConfigEntryBase)(object)rosaryRandomizerType); } else { SettingMenu.UpdateSubMenuColor((ConfigEntryBase)(object)shardRandomizerType); } } private protected override void OnSettingsUpdated(object sender, EventArgs args) { } private void OnRosarySettingsUpdated(object sender, EventArgs args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (((SettingChangedEventArgs)args).ChangedSetting.BoxedValue is RandomizeByRangeTypes randomizeByRangeTypes && !randomizeByRangeTypes.Equals(currentRosarySetting)) { if (currentShardSetting.Equals(RandomizeByRangeTypes.Disabled)) { if (randomizeByRangeTypes.Equals(RandomizeByRangeTypes.Disabled) && !currentRosarySetting.Equals(RandomizeByRangeTypes.Disabled)) { Unregister(); SettingMenu.UpdateSubMenuColor((ConfigEntryBase)(object)rosaryRandomizerType); } if (currentRosarySetting.Equals(RandomizeByRangeTypes.Disabled) && !randomizeByRangeTypes.Equals(RandomizeByRangeTypes.Disabled)) { Register(); SettingMenu.UpdateSubMenuColor((ConfigEntryBase)(object)rosaryRandomizerType); } } currentRosarySetting = randomizeByRangeTypes; } enemyGeoSets.Clear(); sceneGeoSets.Clear(); } private void OnShardSettingsUpdated(object sender, EventArgs args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (((SettingChangedEventArgs)args).ChangedSetting.BoxedValue is RandomizeByRangeTypes randomizeByRangeTypes && !randomizeByRangeTypes.Equals(currentShardSetting)) { if (currentRosarySetting.Equals(RandomizeByRangeTypes.Disabled)) { if (randomizeByRangeTypes.Equals(RandomizeByRangeTypes.Disabled) && !currentShardSetting.Equals(RandomizeByRangeTypes.Disabled)) { Unregister(); SettingMenu.UpdateSubMenuColor((ConfigEntryBase)(object)shardRandomizerType); } if (currentShardSetting.Equals(RandomizeByRangeTypes.Disabled) && !randomizeByRangeTypes.Equals(RandomizeByRangeTypes.Disabled)) { Register(); SettingMenu.UpdateSubMenuColor((ConfigEntryBase)(object)shardRandomizerType); } } currentShardSetting = randomizeByRangeTypes; } enemyShards.Clear(); sceneShards.Clear(); } } internal record RandomizedGeoSet { public int SmallGeo { get; private set; } public int MediumGeo { get; private set; } public int LargeGeo { get; private set; } [JsonConstructor] public RandomizedGeoSet(int SmallGeo = 0, int MediumGeo = 0, int LargeGeo = 0) { this.SmallGeo = SmallGeo; this.MediumGeo = MediumGeo; this.LargeGeo = LargeGeo; } public RandomizedGeoSet(HealthManager thing) : this((int)CuteRandoCore.TraverseHelper(thing, "smallGeoDrops").GetValue(), (int)CuteRandoCore.TraverseHelper(thing, "mediumGeoDrops").GetValue(), (int)CuteRandoCore.TraverseHelper(thing, "largeGeoDrops").GetValue()) { } public void MultiplyGeo(float multiplier) { checked { SmallGeo = (int)Math.Round((float)SmallGeo * multiplier); MediumGeo = (int)Math.Round((float)MediumGeo * multiplier); LargeGeo = (int)Math.Round((float)LargeGeo * multiplier); } } public void SetGeoQuantity(int quantity) { LargeGeo = quantity / Enemy_Currency_Rando.largeGeoValue; MediumGeo = quantity % Enemy_Currency_Rando.largeGeoValue / Enemy_Currency_Rando.mediumGeoValue; SmallGeo = quantity % Enemy_Currency_Rando.largeGeoValue % Enemy_Currency_Rando.mediumGeoValue / Enemy_Currency_Rando.smallGeoValue; } } internal class Enemy_Damage_Rando : Rando_Base { private static readonly Lazy<Enemy_Damage_Rando> instance = new Lazy<Enemy_Damage_Rando>(() => new Enemy_Damage_Rando()); private readonly Dictionary<string, int> enemyDamageNumbers = new Dictionary<string, int>(); private readonly Dictionary<string, Dictionary<string, int>> sceneDamageNumbers = new Dictionary<string, Dictionary<string, int>>(); private readonly HashSet<DamageHero> currentHeroDamagers = new HashSet<DamageHero>(); private Randomizer_Info eventActiveHeroDamager; private Randomizer_Info eventOnFirstSceneFrame; private ConfigEntry<RandomizerConsistencyA> randomizerConsistency; public readonly RandomizerConsistencyA defaultRandomizerConsistency; private ConfigEntry<RandomizeByFlatAmount> damageModifierType; public readonly RandomizeByFlatAmount defaultDamageModifierType; private ConfigEntry<int> damageShift; public readonly int defaultDamageShift = 1; private ConfigEntry<IntRange> damageRange; public readonly IntRange defaultDamageRange = new IntRange(0, 3); private ConfigEntry<bool> enemyDamageMinimum; public readonly bool defaultEnemyDamageMinimum; private ConfigEntry<bool> enemyAttackConsistancy; public readonly bool defaultEnemyAttackConsistancy = true; private RandomizeByFlatAmount currentDamageModifierType; public static Enemy_Damage_Rando Instance => instance.Value; public RandomizerConsistencyA RandomizerConsistency { get { return randomizerConsistency.Value; } internal set { randomizerConsistency.Value = value; } } public RandomizeByFlatAmount DamageModifierType { get { return damageModifierType.Value; } internal set { damageModifierType.Value = value; } } public int DamageShift { get { return damageShift.Value; } internal set { damageShift.Value = value; } } public IntRange DamageRange { get { return damageRange.Value; } internal set { damageRange.Value = value; } } public bool EnemyDamageMinimum { get { return enemyDamageMinimum.Value; } internal set { enemyDamageMinimum.Value = value; } } public bool EnemyAttackConsistancy { get { return enemyAttackConsistancy.Value; } internal set { enemyAttackConsistancy.Value = value; } } private Enemy_Damage_Rando() { InitRandomizer(); } private protected override void InitRandomizer() { RandomizerName = "Enemy Damage Randomizer"; RandomizerDescription = "Randomizes the damage delt to Hornet by enemies and bosses."; if (CuteRandoCore.RegisterRandomizer(new Randomizer_Info(RandomizerName, RandomizerEventType.GameStartup, AccessTools.Method(typeof(Enemy_Damage_Rando), "GameStartup", (Type[])null, (Type[])null), this))) { eventActiveHeroDamager = new Randomizer_Info(RandomizerName, RandomizerEventType.ActiveHeroDamager, AccessTools.Method(typeof(Enemy_Damage_Rando), "SetDamage", (Type[])null, (Type[])null), this); eventOnFirstSceneFrame = new Randomizer_Info(RandomizerName, RandomizerEventType.OnFirstSceneFrame, AccessTools.Method(typeof(Enemy_Damage_Rando), "OnFirstSceneFrame", (Type[])null, (Type[])null), this); base.InitRandomizer(); } } private protected override void Register() { CuteRandoCore.RegisterRandomizer(eventActiveHeroDamager); CuteRandoCore.RegisterRandomizer(eventOnFirstSceneFrame); } private protected override void Unregister() { CuteRandoCore.UnregisterRandomizer(eventActiveHeroDamager); CuteRandoCore.UnregisterRandomizer(eventOnFirstSceneFrame); } private void GameStartup() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown CuteRandoCore.harmony.Patch((MethodBase)AccessTools.Method(typeof(DamageHero), "OnEnable", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Enemy_Damage_Rando), "DamageHeroOnEnablePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private void OnFirstSceneFrame() { CleanCurrentHeroDamagers(); } private static void DamageHeroOnEnablePostfix(ref DamageHero __instance, ref HealthManager ___healthManager) { if (Instance.coreEnableRandomization && Instance.DamageModifierType != RandomizeByFlatAmount.Disabled && Instance.currentHeroDamagers.Add(__instance)) { Instance.SetDamage(__instance, ___healthManager); } } private void SetDamage(DamageHero damager, HealthManager enemyHealthManager) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)damager == (Object)null || (int)damager.hazardType != 1) { return; } Scene scene = ((Component)damager).gameObject.scene; string name = ((Scene)(ref scene)).name; int value = damager.damageDealt; string text = ((Object)damager).name; int num = text.IndexOf('('); if (num > 0) { text = text.Substring(0, num).TrimEnd(' '); } checked { if (EnemyAttackConsistancy && (Object)(object)enemyHealthManager != (Object)null) { string text2 = ((Object)enemyHealthManager).name; num = text2.IndexOf('('); if (num > 0) { text2 = text2.Substring(0, num).TrimEnd(' '); } if (text != text2 && char.IsDigit(text, text.Length - 1)) { do { text = text.Substring(0, text.Length - 1); } while (char.IsDigit(text, text.Length - 1)); if (text.LastIndexOf(' ') == text.Length - 1) { text = text.Substring(0, text.Length - 1); } } } switch (RandomizerConsistency) { case RandomizerConsistencyA.EnemyType: if (!enemyDamageNumbers.TryGetValue(text, out value)) { DamageSetter(ref value, CuteRandoCore.RNGSeed(text)); enemyDamageNumbers[text] = value; } damager.damageDealt = value; break; case RandomizerConsistencyA.Scene: { if (!sceneDamageNumbers.TryGetValue(name, out Dictionary<string, int> value2)) { DamageSetter(ref value, CuteRandoCore.RNGSeed(text + name)); sceneDamageNumbers[name] = new Dictionary<string, int> { { text, value } }; } else if (!value2.TryGetValue(text, out value)) { DamageSetter(ref value, CuteRandoCore.RNGSeed(text + name)); value2[text] = value; } damager.damageDealt = value; break; } case RandomizerConsistencyA.None: DamageSetter(ref damager.damageDealt); break; default: throw new NotImplementedException(); } } void DamageSetter(ref int damage, int seed = int.MinValue) { checked { if (DamageModifierType == RandomizeByFlatAmount.Shift) { damage += CuteRandoCore.RandoHelper(DamageShift * -1, DamageShift, seed); } else if (DamageModifierType == RandomizeByFlatAmount.Range) { damage = CuteRandoCore.RandoHelper(DamageRange.AsTuple(), seed); } if (damage <= 0 && EnemyDamageMinimum) { damage = 1; } else if (damage < 0) { damage = 0; } } } } private void CleanCurrentHeroDamagers() { currentHeroDamagers.RemoveWhere((DamageHero x) => (Object)(object)x == (Object)null); } private protected override void ResetAllLists() { currentHeroDamagers.Clear(); enemyDamageNumbers.Clear(); sceneDamageNumbers.Clear(); } private protected override void InitSettings() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown ConfigFile configFile = Smol_Randomizer.Settings.Settings.ConfigFile; damageModifierType = configFile.Bind<RandomizeByFlatAmount>(RandomizerName, "Enemy Damage Modifier Type", defaultDamageModifierType, new ConfigDescription("Damage modifier type. Shift adjusts by a random amount. Range randomizes within a range.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 5 } })); randomizerConsistency = configFile.Bind<RandomizerConsistencyA>(RandomizerName, "Damage Consistancy", defaultRandomizerConsistency, new ConfigDescription("Setting for if the enemy damage should be consistent per enemy type or room.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 4 } })); damageShift = configFile.Bind<int>(RandomizerName, "Damage Shift", defaultDamageShift, new ConfigDescription("Set damage shift amount. Acceptable values range from 0 to 10.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), new object[1] { new ConfigurationManagerAttributes { Order = 3 } })); damageRange = configFile.Bind<IntRange>(RandomizerName, "Damage Range", defaultDamageRange, new ConfigDescription("Set damage range.", (AcceptableValueBase)(object)new AcceptableRangeforIntRange(0, 10), new object[1] { new ConfigurationManagerAttributes { Order = 2, CustomDrawer = Smol_Randomizer.Settings.Settings.RangeDrawer } })); enemyDamageMinimum = configFile.Bind<bool>(RandomizerName, "Enemy Damage Minimum", defaultEnemyDamageMinimum, new ConfigDescription("Enforces a minimum damage for enemies to be 1. Overrides set values.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 1 } })); enemyAttackConsistancy = configFile.Bind<bool>(RandomizerName, "Enemy Attack Consistancy", defaultEnemyAttackConsistancy, new ConfigDescription("Makes each part of an attack do the same damage.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 0 } })); currentDamageModifierType = damageModifierType.Value; damageModifierType.SettingChanged += OnSettingsUpdated; damageShift.SettingChanged += OnSettingsUpdated; damageRange.SettingChanged += OnSettingsUpdated; enemyAttackConsistancy.SettingChanged += OnSettingsUpdated; damageModifierType.SettingChanged += SettingMenu.OnRandomizerEnable; SettingMenu.UpdateSubMenuColor((ConfigEntryBase)(object)damageModifierType); } private protected override void OnSettingsUpdated(object sender, EventArgs args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (((SettingChangedEventArgs)args).ChangedSetting.BoxedValue is RandomizeByFlatAmount randomizeByFlatAmount && !randomizeByFlatAmount.Equals(currentDamageModifierType)) { if (randomizeByFlatAmount.Equals(RandomizeByFlatAmount.Disabled) && !currentDamageModifierType.Equals(RandomizeByFlatAmount.Disabled)) { Unregister(); } if (currentDamageModifierType.Equals(RandomizeByFlatAmount.Disabled) && !randomizeByFlatAmount.Equals(RandomizeByFlatAmount.Disabled)) { Register(); } currentDamageModifierType = randomizeByFlatAmount; } ResetAllLists(); } } internal class Enemy_Health_Rando : Rando_Base { private static readonly Lazy<Enemy_Health_Rando> instance = new Lazy<Enemy_Health_Rando>(() => new Enemy_Health_Rando()); private readonly Dictionary<string, int> enemyHealthNumbers = new Dictionary<string, int>(); private readonly Dictionary<string, Dictionary<string, int>> sceneHealthNumbers = new Dictionary<string, Dictionary<string, int>>(); private readonly HashSet<HealthManager> currentEnemyHealthManagers = new HashSet<HealthManager>(); private Randomizer_Info eventActiveEnemy; private Randomizer_Info eventOnFirstSceneFrame; private ConfigEntry<RandomizerConsistencyA> randomizerConsistency; public readonly RandomizerConsistencyA defaultRandomizerConsistency; private ConfigEntry<RandomizerEnemyTypeFlags> enemyHealthRandomizerSetting; public readonly RandomizerEnemyTypeFlags defaultEnemyHealthRandomizerSetting; private ConfigEntry<FloatRange> enemyHealthPercentRange; public readonly FloatRange defaultEnemyHealthPercentRange = new FloatRange(0.25f, 3f); private ConfigEntry<FloatRange> bossHealthPercentRange; public readonly FloatRange defaultBossHealthPercentRange = new FloatRange(0.75f, 1.25f); private RandomizerEnemyTypeFlags currentHealthRandomizerSetting; public static Enemy_Health_Rando Instance => instance.Value; public RandomizerConsistencyA RandomizerConsistency { get { return randomizerConsistency.Value; } internal set { randomizerConsistency.Value = value; } } public RandomizerEnemyTypeFlags EnemyHealthRandomizerSetting { get { return enemyHealthRandomizerSetting.Value; } internal set { enemyHealthRandomizerSetting.Value = value; } } public FloatRange EnemyHealthPercentRange { get { return enemyHealthPercentRange.Value; } internal set { enemyHealthPercentRange.Value = value; } } public FloatRange BossHealthPercentRange { get { return bossHealthPercentRange.Value; } internal set { bossHealthPercentRange.Value = value; } } private Enemy_Health_Rando() { InitRandomizer(); } private protected override void InitRandomizer() { RandomizerName = "Enemy Health Randomizer"; RandomizerDescription = "Randomizes the health of enemies and bosses."; if (CuteRandoCore.RegisterRandomizer(new Randomizer_Info(RandomizerName, RandomizerEventType.GameStartup, AccessTools.Method(typeof(Enemy_Health_Rando), "GameStartup", (Type[])null, (Type[])null), this))) { eventActiveEnemy = new Randomizer_Info(RandomizerName, RandomizerEventType.ActiveEnemy, AccessTools.Method(typeof(Enemy_Health_Rando), "SetHealth", (Type[])null, (Type[])null), this); eventOnFirstSceneFrame = new Randomizer_Info(RandomizerName, RandomizerEventType.OnFirstSceneFrame, AccessTools.Method(typeof(Enemy_Health_Rando), "OnFirstSceneFrame", (Type[])null, (Type[])null), this); base.InitRandomizer(); } } private protected override void Register() { CuteRandoCore.RegisterRandomizer(eventActiveEnemy); CuteRandoCore.RegisterRandomizer(eventOnFirstSceneFrame); } private protected override void Unregister() { CuteRandoCore.UnregisterRandomizer(eventActiveEnemy); CuteRandoCore.UnregisterRandomizer(eventOnFirstSceneFrame); } private void GameStartup() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown CuteRandoCore.harmony.Patch((MethodBase)AccessTools.Method(typeof(HealthManager), "OnEnable", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Enemy_Health_Rando), "HealthManagerOnEnablePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private void OnFirstSceneFrame() { CleanCurrentHealthManagerList(); } internal static void HealthManagerOnEnablePostfix(ref HealthManager __instance, ref int ___initHp, ref int ___hp) { if (Instance.coreEnableRandomization && Instance.EnemyHealthRandomizerSetting != RandomizerEnemyTypeFlags.None && Instance.currentEnemyHealthManagers.Add(__instance)) { Instance.SetHealth(__instance, ref ___initHp, ref ___hp); } } private void SetHealth(HealthManager thing, ref int initHp, ref int hp) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)thing == (Object)null) { return; } bool flag = CuteRandoCore.IsBoss(thing); if (flag && !EnemyHealthRandomizerSetting.HasFlag(RandomizerEnemyTypeFlags.Boss)) { return; } Scene scene = ((Component)thing).gameObject.scene; string name = ((Scene)(ref scene)).name; string text = ((Object)thing).name; int num = checked(text.IndexOf('(') - 1); if (num > 0) { text = text.Substring(0, num); } int value2; switch (RandomizerConsistency) { case RandomizerConsistencyA.EnemyType: if (enemyHealthNumbers.TryGetValue(text, out value2)) { hp = (initHp = value2); } else { enemyHealthNumbers.Add(text, RandomizeHp(flag, ref initHp, ref hp, CuteRandoCore.RNGSeed(text))); } break; case RandomizerConsistencyA.Scene: { if (sceneHealthNumbers.TryGetValue(name, out Dictionary<string, int> value)) { if (value.TryGetValue(text, out value2)) { hp = (initHp = value2); } else { value[text] = RandomizeHp(flag, ref initHp, ref hp, CuteRandoCore.RNGSeed(text + name)); } } else { sceneHealthNumbers[name] = new Dictionary<string, int> { { text, RandomizeHp(flag, ref initHp, ref hp, CuteRandoCore.RNGSeed(text + name)) } }; } break; } case RandomizerConsistencyA.None: RandomizeHp(flag, ref initHp, ref hp); break; default: throw new NotImplementedException(); } int RandomizeHp(bool boss, ref int reference, ref int reference2, int seed = int.MinValue) { float num2 = CuteRandoCore.RandoHelper(boss ? BossHealthPercentRange.AsTuple() : EnemyHealthPercentRange.AsTuple(), seed); checked { int num3; if (reference <= 0) { num3 = (int)Math.Round((float)reference2 * num2); reference2 = (reference = num3); } else { num3 = (int)Math.Round((float)reference * num2); reference2 = (reference = num3); } return num3; } } } private void CleanCurrentHealthManagerList() { currentEnemyHealthManagers.RemoveWhere((HealthManager x) => (Object)(object)x == (Object)null); } private protected override void ResetAllLists() { currentEnemyHealthManagers.Clear(); enemyHealthNumbers.Clear(); sceneHealthNumbers.Clear(); } private protected override void InitSettings() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown ConfigFile configFile = Smol_Randomizer.Settings.Settings.ConfigFile; enemyHealthRandomizerSetting = configFile.Bind<RandomizerEnemyTypeFlags>(RandomizerName, "Randomize Health", defaultEnemyHealthRandomizerSetting, new ConfigDescription("Allow randomization of enemy and/or boss health.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 3 } })); randomizerConsistency = configFile.Bind<RandomizerConsistencyA>(RandomizerName, "Health Consistency", defaultRandomizerConsistency, new ConfigDescription("Setting for if the enemy health should be consistent per enemy type or room.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 2 } })); enemyHealthPercentRange = configFile.Bind<FloatRange>(RandomizerName, "Enemy Health Range", defaultEnemyHealthPercentRange, new ConfigDescription("Randomize regular enemy health.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 1, CustomDrawer = Smol_Randomizer.Settings.Settings.RangeDrawer } })); bossHealthPercentRange = configFile.Bind<FloatRange>(RandomizerName, "Boss Health Range", defaultBossHealthPercentRange, new ConfigDescription("Randomize boss health.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 0, CustomDrawer = Smol_Randomizer.Settings.Settings.RangeDrawer } })); currentHealthRandomizerSetting = enemyHealthRandomizerSetting.Value; enemyHealthRandomizerSetting.SettingChanged += OnSettingsUpdated; enemyHealthPercentR