Decompiled source of Difficulty Editor v1.0.0

RepoDifficultyConfigurator.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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;
		}
	}
}
namespace RepoDifficultyConfigurator
{
	[HarmonyPatch(typeof(LevelGenerator), "TileGeneration")]
	internal static class LevelGenerator_TileGeneration_Patch
	{
		private static readonly FieldInfo ModuleAmount = AccessTools.Field(typeof(LevelGenerator), "ModuleAmount");

		private static readonly FieldInfo LevelGrid = AccessTools.Field(typeof(LevelGenerator), "LevelGrid");

		private static void Postfix(LevelGenerator __instance, ref IEnumerator __result)
		{
		}

		private static IEnumerator AddRoomsAfterTileGeneration(LevelGenerator generator, IEnumerator original)
		{
			while (original.MoveNext())
			{
				yield return original.Current;
			}
			try
			{
				if (!(LevelGrid.GetValue(generator) is Array grid))
				{
					yield break;
				}
				int addedRooms = 0;
				for (int i = 0; i < Plugin.AdditionalRooms.Value; i++)
				{
					List<object> candidates = new List<object>();
					for (int x = 0; x < generator.LevelWidth; x++)
					{
						for (int y = 0; y < generator.LevelHeight; y++)
						{
							object tile = grid.GetValue(x, y);
							if (tile != null && !IsTileActive(tile) && IsAdjacentToActive(grid, generator.LevelWidth, generator.LevelHeight, x, y))
							{
								candidates.Add(tile);
							}
						}
					}
					if (candidates.Count == 0)
					{
						break;
					}
					object tileToAdd = candidates[Random.Range(0, candidates.Count)];
					SetTileField(tileToAdd, "active", true);
					SetTileField(tileToAdd, "type", 0);
					addedRooms++;
				}
				int addedExtractionRooms = EnforceExtractionTopology(grid, generator.LevelWidth, generator.LevelHeight);
				int addedTotal = addedRooms + addedExtractionRooms;
				if (addedTotal > 0)
				{
					ModuleAmount.SetValue(generator, (int)ModuleAmount.GetValue(generator) + addedTotal);
				}
				Plugin.Log.LogInfo((object)("Rooms: added " + addedRooms + " of " + Plugin.AdditionalRooms.Value + " requested connected rooms."));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not add rooms: " + ex));
			}
		}

		private static bool IsAdjacentToActive(Array grid, int width, int height, int x, int y)
		{
			return IsActive(grid, width, height, x + 1, y) || IsActive(grid, width, height, x - 1, y) || IsActive(grid, width, height, x, y + 1) || IsActive(grid, width, height, x, y - 1);
		}

		private static bool IsActive(Array grid, int width, int height, int x, int y)
		{
			if (x < 0 || x >= width || y < 0 || y >= height)
			{
				return false;
			}
			object value = grid.GetValue(x, y);
			return value != null && IsTileActive(value);
		}

		private static bool IsTileActive(object tile)
		{
			return (bool)AccessTools.Field(tile.GetType(), "active").GetValue(tile);
		}

		private static void SetTileField(object tile, string name, object value)
		{
			FieldInfo fieldInfo = AccessTools.Field(tile.GetType(), name);
			fieldInfo.SetValue(tile, fieldInfo.FieldType.IsEnum ? Enum.ToObject(fieldInfo.FieldType, value) : value);
		}

		private static int EnforceExtractionTopology(Array grid, int width, int height)
		{
			List<object> list = new List<object>();
			for (int i = 0; i < width; i++)
			{
				for (int j = 0; j < height; j++)
				{
					object value = grid.GetValue(i, j);
					if (value != null && IsTileActive(value) && GetTileType(value) == 3)
					{
						list.Add(value);
					}
				}
			}
			int num = list.Count + Plugin.AdditionalExtractionPoints.Value;
			foreach (object item in list)
			{
				if (ActiveNeighbourCount(grid, width, height, GetTileInt(item, "x"), GetTileInt(item, "y")) != 1)
				{
					SetTileField(item, "type", 0);
				}
			}
			int k;
			for (k = CountExtractionTiles(grid, width, height); k < num; k++)
			{
				object obj = null;
				for (int l = 0; l < width; l++)
				{
					if (obj != null)
					{
						break;
					}
					for (int m = 0; m < height; m++)
					{
						object value2 = grid.GetValue(l, m);
						if (value2 != null && IsTileActive(value2) && !GetTileBool(value2, "first") && GetTileType(value2) != 3 && ActiveNeighbourCount(grid, width, height, l, m) == 1)
						{
							obj = value2;
							break;
						}
					}
				}
				if (obj == null)
				{
					break;
				}
				SetTileField(obj, "type", 3);
			}
			int num2 = 0;
			while (k < num)
			{
				object obj2 = null;
				for (int n = 0; n < width; n++)
				{
					if (obj2 != null)
					{
						break;
					}
					for (int num3 = 0; num3 < height; num3++)
					{
						object value3 = grid.GetValue(n, num3);
						if (value3 != null && !IsTileActive(value3) && ActiveNeighbourCount(grid, width, height, n, num3) == 1)
						{
							obj2 = value3;
							break;
						}
					}
				}
				if (obj2 == null)
				{
					break;
				}
				SetTileField(obj2, "active", true);
				SetTileField(obj2, "type", 3);
				k++;
				num2++;
			}
			Plugin.Log.LogInfo((object)("Extraction points: " + k + " of " + num + " placed on one-entrance edge rooms. Quota unchanged."));
			return num2;
		}

		private static int CountExtractionTiles(Array grid, int width, int height)
		{
			int num = 0;
			for (int i = 0; i < width; i++)
			{
				for (int j = 0; j < height; j++)
				{
					object value = grid.GetValue(i, j);
					if (value != null && IsTileActive(value) && GetTileType(value) == 3)
					{
						num++;
					}
				}
			}
			return num;
		}

		private static int ActiveNeighbourCount(Array grid, int width, int height, int x, int y)
		{
			int num = 0;
			if (IsActive(grid, width, height, x + 1, y))
			{
				num++;
			}
			if (IsActive(grid, width, height, x - 1, y))
			{
				num++;
			}
			if (IsActive(grid, width, height, x, y + 1))
			{
				num++;
			}
			if (IsActive(grid, width, height, x, y - 1))
			{
				num++;
			}
			return num;
		}

		private static int GetTileType(object tile)
		{
			return Convert.ToInt32(AccessTools.Field(tile.GetType(), "type").GetValue(tile));
		}

		private static int GetTileInt(object tile, string name)
		{
			return (int)AccessTools.Field(tile.GetType(), name).GetValue(tile);
		}

		private static bool GetTileBool(object tile, string name)
		{
			return (bool)AccessTools.Field(tile.GetType(), name).GetValue(tile);
		}

		private static bool IsHostOrSingle()
		{
			try
			{
				return SemiFunc.IsMasterClientOrSingleplayer();
			}
			catch
			{
				return true;
			}
		}
	}
	[HarmonyPatch]
	internal static class LevelGenerator_TileGeneration_Coroutine_Patch
	{
		private static readonly FieldInfo ModuleAmount = AccessTools.Field(typeof(LevelGenerator), "ModuleAmount");

		private static readonly FieldInfo ExtractionAmount = AccessTools.Field(typeof(LevelGenerator), "ExtractionAmount");

		private static MethodBase TargetMethod()
		{
			Type type = typeof(LevelGenerator).GetNestedTypes(BindingFlags.NonPublic).FirstOrDefault((Type type2) => type2.Name.StartsWith("<TileGeneration>d__", StringComparison.Ordinal));
			return (type == null) ? null : AccessTools.Method(type, "MoveNext", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo methodInfo = AccessTools.Method(typeof(LevelGenerator_TileGeneration_Coroutine_Patch), "ApplyRoomCount", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(LevelGenerator_TileGeneration_Coroutine_Patch), "ApplyExtractionCount", (Type[])null, (Type[])null);
			int num = list.FindLastIndex((CodeInstruction code) => code.opcode == OpCodes.Stfld && (code.operand as FieldInfo)?.Name == "ModuleAmount");
			if (num >= 0)
			{
				list.Insert(num + 1, new CodeInstruction(OpCodes.Ldloc_1, (object)null));
				list.Insert(num + 2, new CodeInstruction(OpCodes.Call, (object)methodInfo));
			}
			int num2 = list.FindIndex((CodeInstruction code) => code.opcode == OpCodes.Call && (code.operand as MethodInfo)?.Name == "IsLevelShop");
			if (num2 >= 0)
			{
				list.Insert(num2, new CodeInstruction(OpCodes.Ldloc_1, (object)null));
				list.Insert(num2 + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo2));
			}
			return list;
		}

		private static void ApplyRoomCount(LevelGenerator generator)
		{
			if (IsHostOrSingle() && Plugin.AdditionalRooms.Value > 0)
			{
				int num = (int)ModuleAmount.GetValue(generator);
				ModuleAmount.SetValue(generator, num + Plugin.AdditionalRooms.Value);
				Plugin.Log.LogInfo((object)("Rooms: " + num + " -> " + (num + Plugin.AdditionalRooms.Value) + "."));
			}
		}

		private static void ApplyExtractionCount(LevelGenerator generator)
		{
			if (IsHostOrSingle() && Plugin.AdditionalExtractionPoints.Value > 0)
			{
				int num = (int)ExtractionAmount.GetValue(generator);
				ExtractionAmount.SetValue(generator, num + Plugin.AdditionalExtractionPoints.Value);
				Plugin.Log.LogInfo((object)("Extraction points: " + num + " -> " + (num + Plugin.AdditionalExtractionPoints.Value) + ". Quota unchanged."));
			}
		}

		private static bool IsHostOrSingle()
		{
			try
			{
				return SemiFunc.IsMasterClientOrSingleplayer();
			}
			catch
			{
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(ValuableDirector), "SpawnValuable")]
	internal static class ValuableDirector_SpawnValuable_Patch
	{
		private static readonly FieldInfo TotalMaxValue = AccessTools.Field(typeof(ValuableDirector), "totalMaxValue");

		private static readonly FieldInfo TotalMaxAmount = AccessTools.Field(typeof(ValuableDirector), "totalMaxAmount");

		private static readonly FieldInfo LevelGeneratorInstance = AccessTools.Field(typeof(LevelGenerator), "Instance");

		private static readonly FieldInfo ModuleAmount = AccessTools.Field(typeof(LevelGenerator), "ModuleAmount");

		private static readonly FieldInfo ExtractionAmount = AccessTools.Field(typeof(LevelGenerator), "ExtractionAmount");

		private static readonly HashSet<ValuableDirector> AdjustedDirectors = new HashSet<ValuableDirector>();

		private static void Prefix(ValuableDirector __instance)
		{
			if ((Object)(object)__instance == (Object)null || !IsHostOrSingle() || !Plugin.ScaleValuableLoot.Value || AdjustedDirectors.Contains(__instance))
			{
				return;
			}
			try
			{
				object? obj = LevelGeneratorInstance?.GetValue(null);
				LevelGenerator val = (LevelGenerator)((obj is LevelGenerator) ? obj : null);
				if (!((Object)(object)val == (Object)null) && !(TotalMaxValue == null) && !(TotalMaxAmount == null))
				{
					int num = Math.Max(1, ReadInt(ModuleAmount, val));
					int val2 = Math.Max(1, ReadInt(ExtractionAmount, val));
					int num2 = Math.Max(val2, (int)Math.Ceiling((double)num / 6.0));
					int num3 = Math.Min(Plugin.MinimumValuePerQuota.Value, Plugin.MaximumValuePerQuota.Value);
					int num4 = Math.Max(Plugin.MinimumValuePerQuota.Value, Plugin.MaximumValuePerQuota.Value);
					int num5 = Random.Range(num3, num4 + 1);
					int num6 = num2 * num5;
					int num7 = Math.Max(1, ReadInt(TotalMaxValue, __instance));
					int num8 = Math.Max(1, ReadInt(TotalMaxAmount, __instance));
					float num9 = (float)num6 / (float)num7;
					WriteNumber(TotalMaxValue, __instance, num6);
					WriteNumber(TotalMaxAmount, __instance, Math.Max(num8, (int)Math.Ceiling((float)num8 * num9)));
					AdjustedDirectors.Add(__instance);
					Plugin.Log.LogInfo((object)("Loot target: " + num6 + " (" + num2 + " quota units × " + num5 + "). Rooms: " + num + ", extraction points: " + val2 + "."));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not scale valuable loot: " + ex));
			}
		}

		private static int ReadInt(FieldInfo field, object instance)
		{
			return Convert.ToInt32(field.GetValue(instance));
		}

		private static void WriteNumber(FieldInfo field, object instance, int value)
		{
			Type fieldType = field.FieldType;
			field.SetValue(instance, (fieldType == typeof(float)) ? ((object)(float)value) : ((fieldType == typeof(double)) ? ((object)(double)value) : ((fieldType == typeof(long)) ? ((object)(long)value) : ((fieldType == typeof(decimal)) ? ((object)(decimal)value) : ((object)value)))));
		}

		private static bool IsHostOrSingle()
		{
			try
			{
				return SemiFunc.IsMasterClientOrSingleplayer();
			}
			catch
			{
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(EnemyDirector), "AmountSetup")]
	internal static class EnemyDirector_AmountSetup_Patch
	{
		private static readonly FieldInfo TotalAmount = AccessTools.Field(typeof(EnemyDirector), "totalAmount");

		private static readonly FieldInfo EnemyList = AccessTools.Field(typeof(EnemyDirector), "enemyList");

		private static readonly FieldInfo EnemyListCurrent = AccessTools.Field(typeof(EnemyDirector), "enemyListCurrent");

		private static void Postfix(EnemyDirector __instance)
		{
			if ((Object)(object)__instance == (Object)null || !IsHostOrSingle())
			{
				return;
			}
			try
			{
				string details;
				int num = DuplicateVanillaSelections(__instance, out details);
				if (num != 0)
				{
					TotalAmount?.SetValue(__instance, (int)TotalAmount.GetValue(__instance) + num);
					Plugin.Log.LogInfo((object)("Added " + num + " configured copies of monster types selected by vanilla generation."));
					Plugin.Log.LogInfo((object)("Monster matching: " + details));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not add configured monsters: " + ex));
			}
		}

		private static int DuplicateVanillaSelections(EnemyDirector director, out string details)
		{
			details = "no vanilla enemy selections";
			List<EnemySetup> list = EnemyList?.GetValue(director) as List<EnemySetup>;
			List<EnemySetup> list2 = EnemyListCurrent?.GetValue(director) as List<EnemySetup>;
			if (list == null || list2 == null)
			{
				return 0;
			}
			Dictionary<string, EnemySetup> dictionary = new Dictionary<string, EnemySetup>(StringComparer.OrdinalIgnoreCase);
			foreach (EnemySetup item in list)
			{
				string spawnName = GetSpawnName(item);
				if (!string.IsNullOrEmpty(spawnName) && !dictionary.ContainsKey(Plugin.Normalize(spawnName)))
				{
					dictionary[Plugin.Normalize(spawnName)] = item;
				}
			}
			int num = 0;
			List<string> list3 = new List<string>();
			foreach (KeyValuePair<string, EnemySetup> item2 in dictionary)
			{
				EnemySetup value = item2.Value;
				string spawnName2 = GetSpawnName(value);
				int addition = Plugin.GetAddition(spawnName2);
				list3.Add(spawnName2 + " => " + Plugin.Normalize(spawnName2) + " (" + addition + ")");
				for (int i = 0; i < addition; i++)
				{
					if (value.spawnObjects != null && value.spawnObjects.Count != 0 && value.spawnObjects[0] != null)
					{
						list.Add(value);
						list2.Add(value);
						num++;
					}
				}
			}
			details = ((list3.Count == 0) ? "no selected monster types" : string.Join("; ", list3));
			return num;
		}

		private static string GetSpawnName(EnemySetup setup)
		{
			if ((Object)(object)setup == (Object)null || setup.spawnObjects == null || setup.spawnObjects.Count == 0)
			{
				return null;
			}
			PrefabRef val = setup.spawnObjects[0];
			if (val == null)
			{
				return null;
			}
			if (!string.IsNullOrWhiteSpace(((PrefabRef<GameObject>)(object)val).ResourcePath))
			{
				return ((PrefabRef<GameObject>)(object)val).ResourcePath;
			}
			Type type = ((object)val).GetType();
			MemberInfo memberInfo = (MemberInfo)(((object)type.GetProperty("PrefabName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) ?? ((object)type.GetField("PrefabName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)));
			return (!(memberInfo is PropertyInfo propertyInfo)) ? ((!(memberInfo is FieldInfo fieldInfo)) ? ((object)val).ToString() : fieldInfo.GetValue(val)?.ToString()) : propertyInfo.GetValue(val)?.ToString();
		}

		private static bool IsHostOrSingle()
		{
			try
			{
				return SemiFunc.IsMasterClientOrSingleplayer();
			}
			catch
			{
				return true;
			}
		}
	}
	[BepInPlugin("N8917.RepoDifficultyConfigurator", "Difficulty Editor", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "N8917.RepoDifficultyConfigurator";

		public const string PluginName = "Difficulty Editor";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<int> AdditionalRooms;

		internal static ConfigEntry<int> AdditionalExtractionPoints;

		internal static ConfigEntry<bool> ScaleValuableLoot;

		internal static ConfigEntry<int> MinimumValuePerQuota;

		internal static ConfigEntry<int> MaximumValuePerQuota;

		internal static readonly Dictionary<string, ConfigEntry<int>> EnemyAdds = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase);

		private Harmony harmony;

		private static readonly (string Tier, string Name)[] Enemies = new(string, string)[29]
		{
			("Monsters — Tier 1", "Apex Predator"),
			("Monsters — Tier 1", "Bella"),
			("Monsters — Tier 1", "Birthday Boy"),
			("Monsters — Tier 1", "Elsa"),
			("Monsters — Tier 1", "Gnome"),
			("Monsters — Tier 1", "Peeper"),
			("Monsters — Tier 1", "Shadow Child"),
			("Monsters — Tier 1", "Spewer"),
			("Monsters — Tier 1", "Tick"),
			("Monsters — Tier 2", "Animal"),
			("Monsters — Tier 2", "Banger"),
			("Monsters — Tier 2", "Bowtie"),
			("Monsters — Tier 2", "Chef"),
			("Monsters — Tier 2", "Gambit"),
			("Monsters — Tier 2", "Headgrab"),
			("Monsters — Tier 2", "Heart Hugger"),
			("Monsters — Tier 2", "Hidden"),
			("Monsters — Tier 2", "Mentalist"),
			("Monsters — Tier 2", "Oogley"),
			("Monsters — Tier 2", "Rugrat"),
			("Monsters — Tier 2", "Upscream"),
			("Monsters — Tier 3", "Cleanup Crew"),
			("Monsters — Tier 3", "Headman"),
			("Monsters — Tier 3", "Huntsman"),
			("Monsters — Tier 3", "Loom"),
			("Monsters — Tier 3", "Robe"),
			("Monsters — Tier 3", "Trudge"),
			("Monsters — Tier 3", "Reaper"),
			("Monsters — Tier 3", "Clown")
		};

		private void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			AcceptableValueRange<int> val = new AcceptableValueRange<int>(0, 100);
			AdditionalRooms = ((BaseUnityPlugin)this).Config.Bind<int>("Level", "Additional Rooms", 0, new ConfigDescription("Extra rooms added to every generated level. 0 keeps the vanilla amount.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50), Array.Empty<object>()));
			AdditionalExtractionPoints = ((BaseUnityPlugin)this).Config.Bind<int>("Level", "Additional Extraction Points", 0, new ConfigDescription("Extra physical extraction points, not quota money. 0 keeps the vanilla amount.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			ScaleValuableLoot = ((BaseUnityPlugin)this).Config.Bind<bool>("Loot", "Scale Valuable Loot", true, "Sets the level's valuable-loot target according to its rooms and extraction points.");
			MinimumValuePerQuota = ((BaseUnityPlugin)this).Config.Bind<int>("Loot", "Minimum Value Per Quota", 35000, new ConfigDescription("Minimum valuable-loot target for each quota unit.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), Array.Empty<object>()));
			MaximumValuePerQuota = ((BaseUnityPlugin)this).Config.Bind<int>("Loot", "Maximum Value Per Quota", 42000, new ConfigDescription("Maximum valuable-loot target for each quota unit.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), Array.Empty<object>()));
			(string, string)[] enemies = Enemies;
			for (int i = 0; i < enemies.Length; i++)
			{
				(string, string) tuple = enemies[i];
				EnemyAdds[tuple.Item2] = ((BaseUnityPlugin)this).Config.Bind<int>(tuple.Item1, "Additional " + tuple.Item2, 0, new ConfigDescription("Additional " + tuple.Item2 + " enemies. 0 keeps the vanilla amount.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			}
			harmony = new Harmony("N8917.RepoDifficultyConfigurator");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Difficulty Editor 1.0.0 loaded.");
		}

		internal static int GetAddition(string name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return 0;
			}
			string text = Normalize(name);
			foreach (KeyValuePair<string, ConfigEntry<int>> enemyAdd in EnemyAdds)
			{
				if (Normalize(enemyAdd.Key) == text)
				{
					return Math.Max(0, enemyAdd.Value.Value);
				}
			}
			return 0;
		}

		internal static string Normalize(string value)
		{
			string text = value.Replace("(Clone)", "").Trim();
			int num = Math.Max(text.LastIndexOf('/'), text.LastIndexOf('\\'));
			if (num >= 0)
			{
				text = text.Substring(num + 1);
			}
			if (text.StartsWith("Enemy", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(5).TrimStart(' ', '-');
			}
			text = text.Replace(" ", "").Replace("_", "").Replace("-", "")
				.ToLowerInvariant();
			if (1 == 0)
			{
			}
			string result = text switch
			{
				"oogly" => "oogley", 
				"gumbit" => "gambit", 
				"animal" => "animal", 
				"bangdirector" => "banger", 
				"beamer" => "clown", 
				"birthdayboy" => "birthdayboy", 
				"bombthrower" => "cleanupcrew", 
				"bowtie" => "bowtie", 
				"ceilingeye" => "peeper", 
				"duck" => "apexpredator", 
				"elsa" => "elsa", 
				"floater" => "mentalist", 
				"gnomedirector" => "gnome", 
				"head" => "headman", 
				"headgrabber" => "headgrab", 
				"hearthugger" => "hearthugger", 
				"hidden" => "hidden", 
				"hunter" => "huntsman", 
				"robe" => "robe", 
				"runner" => "reaper", 
				"shadow" => "loom", 
				"slowmouth" => "spewer", 
				"slowwalker" => "trudge", 
				"spinny" => "gambit", 
				"thinman" => "shadowchild", 
				"tick" => "tick", 
				"tricycle" => "bella", 
				"tumbler" => "chef", 
				"upscream" => "upscream", 
				"valuablethrower" => "rugrat", 
				_ => text, 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
}