Decompiled source of Smol Randomizer v0.1.1

Smol_Randomizer.dll

Decompiled a day ago
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