Decompiled source of No Limits v0.2.1

plugins/NoLimits/NoLimits.dll

Decompiled 11 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using R2API;
using R2API.Networking;
using R2API.Networking.Interfaces;
using R2API.Utils;
using RoR2;
using RoR2.Items;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.Networking;
using UnityEngine.ResourceManagement.AsyncOperations;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace NoLimits;

internal static class AffineItemRules
{
	private sealed class Count
	{
		internal FieldInfo Item;

		internal List<CodeInstruction> Load;

		internal string Key;
	}

	private sealed class Expr
	{
		internal Count Count;

		internal double Slope;

		internal double Offset;

		internal int Start;

		internal bool Floating;

		internal bool Double;
	}

	private sealed class Rule
	{
		internal int Start;

		internal int End;

		internal Expr Expr;
	}

	[HarmonyPatch]
	private static class ItemMethods
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			Assembly assembly = typeof(Run).Assembly;
			string[] behaviors = RuleTargets.Behaviors;
			foreach (string text in behaviors)
			{
				string[] array = text.Split('|');
				Type type = assembly.GetType(array[0]);
				Type type2 = assembly.GetType(array[1]);
				if (type != null && type2 != null)
				{
					Behaviors[type] = AccessTools.Field(type2, array[2]);
				}
			}
			string[] cachedCounts = RuleTargets.CachedCounts;
			foreach (string text2 in cachedCounts)
			{
				string[] array2 = text2.Split('|');
				Type type3 = assembly.GetType(array2[0]);
				Type type4 = assembly.GetType(array2[2]);
				if (type3 != null && type4 != null)
				{
					FieldInfo fieldInfo = AccessTools.Field(type3, array2[1]);
					FieldInfo fieldInfo2 = AccessTools.Field(type4, array2[3]);
					if (fieldInfo != null && fieldInfo2 != null)
					{
						Cached[fieldInfo] = fieldInfo2;
					}
				}
			}
			HashSet<MethodBase> seen = new HashSet<MethodBase>();
			try
			{
				string[] methods = RuleTargets.Methods;
				foreach (string row in methods)
				{
					string[] parts = row.Split('|');
					Type type5 = assembly.GetType(parts[0]);
					if (type5 == null || type5.ContainsGenericParameters)
					{
						continue;
					}
					try
					{
						MethodInfo[] methods2 = type5.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						foreach (MethodInfo method in methods2)
						{
							if (method.Name == parts[1] && !method.ContainsGenericParameters && method.GetMethodBody() != null && seen.Add(method))
							{
								yield return method;
							}
						}
					}
					finally
					{
					}
				}
			}
			finally
			{
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input, MethodBase __originalMethod)
		{
			List<CodeInstruction> codes = input.ToList();
			Dictionary<int, Count> locals = new Dictionary<int, Count>();
			List<Rule> candidates = new List<Rule>();
			for (int i = 0; i < codes.Count; i++)
			{
				int num = Local(codes[i], store: true);
				if (num >= 0)
				{
					int cursor = i - 1;
					Expr expr = Parse(codes, ref cursor, locals, __originalMethod.DeclaringType, 0);
					if (expr != null && expr.Count != null && expr.Slope == 1.0 && expr.Offset == 0.0)
					{
						locals[num] = new Count
						{
							Item = expr.Count.Item,
							Key = num + ":" + expr.Count.Item.ToString(),
							Load = new List<CodeInstruction>
							{
								new CodeInstruction(OpCodes.Ldloc, (object)(short)num)
							}
						};
					}
					else
					{
						locals.Remove(num);
					}
				}
				MethodInfo methodInfo = codes[i].operand as MethodInfo;
				if (i > 0 && i + 1 < codes.Count && methodInfo != null && methodInfo.DeclaringType == typeof(Inventory) && methodInfo.Name.StartsWith("GetItemCount", StringComparison.Ordinal))
				{
					FieldInfo fieldInfo = codes[i - 1].operand as FieldInfo;
					int num2 = Local(codes[i + 1], store: true);
					if (fieldInfo != null && fieldInfo.FieldType == typeof(ItemDef) && num2 >= 0)
					{
						locals[num2] = new Count
						{
							Item = fieldInfo,
							Key = num2 + ":" + fieldInfo.ToString(),
							Load = new List<CodeInstruction>
							{
								new CodeInstruction(OpCodes.Ldloc, (object)(short)num2)
							}
						};
					}
				}
				if (codes[i].opcode != OpCodes.Add)
				{
					continue;
				}
				int cursor2 = i;
				Expr expr2 = Parse(codes, ref cursor2, locals, __originalMethod.DeclaringType, 0);
				if (expr2 != null && expr2.Count != null && !(expr2.Slope <= 0.0) && !(expr2.Offset <= 0.0) && !double.IsNaN(expr2.Offset) && !double.IsInfinity(expr2.Offset) && !NativeLinear.Contains(expr2.Count.Item.Name))
				{
					if (expr2.Count.Item.Name == "ShieldOnly")
					{
						expr2.Offset = Math.Max(0.0, expr2.Offset - 1.0);
					}
					int j;
					for (j = i + 1; j < codes.Count && (codes[j].opcode == OpCodes.Conv_R4 || codes[j].opcode == OpCodes.Conv_R8); j++)
					{
					}
					if ((j >= codes.Count || !(codes[j].opcode == OpCodes.Div)) && (j + 1 >= codes.Count || !(codes[j + 1].operand is MethodInfo) || !(((MethodInfo)codes[j + 1].operand).Name == "Pow")))
					{
						candidates.Add(new Rule
						{
							Start = expr2.Start,
							End = i,
							Expr = expr2
						});
					}
				}
			}
			List<Rule> rules = candidates.Where((Rule a) => !candidates.Any((Rule b) => b != a && b.Start <= a.Start && b.End > a.End && b.Expr.Count.Key == a.Expr.Count.Key)).ToList();
			int i2;
			for (i2 = 0; i2 < codes.Count; i2++)
			{
				yield return codes[i2];
				foreach (Rule rule in rules.Where((Rule r) => r.End == i2))
				{
					foreach (CodeInstruction load in rule.Expr.Count.Load)
					{
						yield return Clone(load);
					}
					if (rule.Expr.Double)
					{
						yield return new CodeInstruction(OpCodes.Ldc_R8, (object)rule.Expr.Offset);
					}
					else if (rule.Expr.Floating)
					{
						yield return new CodeInstruction(OpCodes.Ldc_R4, (object)(float)rule.Expr.Offset);
					}
					else
					{
						yield return new CodeInstruction(OpCodes.Ldc_I4, (object)(int)rule.Expr.Offset);
					}
					yield return new CodeInstruction(OpCodes.Ldsfld, (object)rule.Expr.Count.Item);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(AffineItemRules), rule.Expr.Double ? "Double" : (rule.Expr.Floating ? "Float" : "Integer"), (Type[])null, (Type[])null));
					PatchedExpressions++;
				}
			}
			if (rules.Count <= 0)
			{
				yield break;
			}
			NoLimitsPlugin.Log.LogInfo((object)("LINEAR " + __originalMethod.DeclaringType.FullName + "." + __originalMethod.Name + " expressions=" + rules.Count));
			foreach (Rule item in rules)
			{
				NoLimitsPlugin.Log.LogInfo((object)("RULE item=" + item.Expr.Count.Item.Name + " site=" + __originalMethod.DeclaringType.FullName + "." + __originalMethod.Name + " slope=" + item.Expr.Slope + " offset=" + item.Expr.Offset));
			}
		}
	}

	internal static int PatchedExpressions;

	private static readonly HashSet<string> NativeLinear = new HashSet<string>
	{
		"Crowbar", "NearbyDamageBonus", "FragileDamageBonus", "BossDamageBonus", "CritDamage", "ShinyPearl", "AllStatBoost", "EquipmentMagazine", "StrengthenBurn", "DroneUpgradeHidden",
		"IncreaseHealing", "RepeatHeal"
	};

	private static readonly Dictionary<Type, FieldInfo> Behaviors = new Dictionary<Type, FieldInfo>();

	private static readonly Dictionary<FieldInfo, FieldInfo> Cached = new Dictionary<FieldInfo, FieldInfo>();

	private static bool Allowed(ItemDef item)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Invalid comparison between Unknown and I4
		if (DifficultyManager.Active && Rules.Enabled(Module.Items) && Object.op_Implicit((Object)(object)item) && !item.hidden)
		{
			return (int)item.tier != 5;
		}
		return false;
	}

	internal static float Float(float original, int count, float offset, ItemDef item)
	{
		if (Allowed(item) && count > 1)
		{
			return (float)Math.Min(3.4028234663852886E+38, (double)original + (double)offset * ((double)count - 1.0));
		}
		return original;
	}

	internal static double Double(double original, int count, double offset, ItemDef item)
	{
		if (Allowed(item) && count > 1)
		{
			return original + offset * ((double)count - 1.0);
		}
		return original;
	}

	internal static int Integer(int original, int count, int offset, ItemDef item)
	{
		if (Allowed(item) && count > 1)
		{
			return (int)Math.Min(2147483647L, original + (long)offset * (long)(count - 1));
		}
		return original;
	}

	private static int Local(CodeInstruction code, bool store)
	{
		OpCode opcode = code.opcode;
		if (store)
		{
			if (opcode == OpCodes.Stloc_0)
			{
				return 0;
			}
			if (opcode == OpCodes.Stloc_1)
			{
				return 1;
			}
			if (opcode == OpCodes.Stloc_2)
			{
				return 2;
			}
			if (opcode == OpCodes.Stloc_3)
			{
				return 3;
			}
			if (opcode != OpCodes.Stloc && opcode != OpCodes.Stloc_S)
			{
				return -1;
			}
		}
		else
		{
			if (opcode == OpCodes.Ldloc_0)
			{
				return 0;
			}
			if (opcode == OpCodes.Ldloc_1)
			{
				return 1;
			}
			if (opcode == OpCodes.Ldloc_2)
			{
				return 2;
			}
			if (opcode == OpCodes.Ldloc_3)
			{
				return 3;
			}
			if (opcode != OpCodes.Ldloc && opcode != OpCodes.Ldloc_S)
			{
				return -1;
			}
		}
		if (code.operand is LocalBuilder localBuilder)
		{
			return localBuilder.LocalIndex;
		}
		if (code.operand is LocalVariableInfo localVariableInfo)
		{
			return localVariableInfo.LocalIndex;
		}
		return Convert.ToInt32(code.operand);
	}

	internal static int LocalIndex(CodeInstruction code, bool store)
	{
		return Local(code, store);
	}

	private static bool Constant(CodeInstruction c, out double value, out bool floating, out bool wide)
	{
		value = 0.0;
		floating = false;
		wide = false;
		if (c.opcode == OpCodes.Ldc_R4 || c.opcode == OpCodes.Ldc_R8)
		{
			value = Convert.ToDouble(c.operand);
			floating = true;
			wide = c.opcode == OpCodes.Ldc_R8;
			return true;
		}
		if (c.opcode == OpCodes.Ldc_I4 || c.opcode == OpCodes.Ldc_I4_S)
		{
			value = Convert.ToDouble(c.operand);
			return true;
		}
		if (c.opcode == OpCodes.Ldc_I4_M1)
		{
			value = -1.0;
			return true;
		}
		short value2 = c.opcode.Value;
		OpCode ldc_I4_ = OpCodes.Ldc_I4_0;
		if (value2 >= ldc_I4_.Value)
		{
			short value3 = c.opcode.Value;
			OpCode ldc_I4_2 = OpCodes.Ldc_I4_8;
			if (value3 <= ldc_I4_2.Value)
			{
				short value4 = c.opcode.Value;
				OpCode ldc_I4_3 = OpCodes.Ldc_I4_0;
				value = value4 - ldc_I4_3.Value;
				return true;
			}
		}
		return false;
	}

	private static Expr Parse(List<CodeInstruction> codes, ref int cursor, Dictionary<int, Count> locals, Type owner, int depth)
	{
		if (cursor < 0 || depth > 12)
		{
			return null;
		}
		int num = cursor;
		CodeInstruction val = codes[cursor--];
		if (Constant(val, out var value, out var floating, out var wide))
		{
			Expr expr = new Expr();
			expr.Offset = value;
			expr.Start = num;
			expr.Floating = floating;
			expr.Double = wide;
			return expr;
		}
		int num2 = Local(val, store: false);
		if (num2 >= 0 && locals.TryGetValue(num2, out var value2))
		{
			Expr expr2 = new Expr();
			expr2.Count = value2;
			expr2.Slope = 1.0;
			expr2.Start = num;
			return expr2;
		}
		MethodInfo methodInfo = val.operand as MethodInfo;
		if (methodInfo != null && methodInfo.DeclaringType == typeof(Inventory) && methodInfo.Name.StartsWith("GetItemCount", StringComparison.Ordinal) && cursor >= 0)
		{
			FieldInfo fieldInfo = codes[cursor].operand as FieldInfo;
			if (fieldInfo != null && fieldInfo.FieldType == typeof(ItemDef))
			{
				int num3 = ReferenceStart(codes, cursor - 1, 0);
				if (num3 >= 0)
				{
					Count count = new Count();
					count.Item = fieldInfo;
					count.Key = "inline:" + fieldInfo.ToString() + ":" + num3;
					count.Load = codes.GetRange(num3, num - num3 + 1).Select(Clone).ToList();
					value2 = count;
					cursor = num3 - 1;
					Expr expr3 = new Expr();
					expr3.Count = value2;
					expr3.Slope = 1.0;
					expr3.Start = num3;
					return expr3;
				}
			}
		}
		if (val.opcode == OpCodes.Conv_R4 || val.opcode == OpCodes.Conv_R8 || val.opcode == OpCodes.Conv_I4 || val.opcode == OpCodes.Conv_U4)
		{
			Expr expr4 = Parse(codes, ref cursor, locals, owner, depth + 1);
			if (expr4 != null)
			{
				expr4.Floating |= val.opcode == OpCodes.Conv_R4 || val.opcode == OpCodes.Conv_R8;
				expr4.Double |= val.opcode == OpCodes.Conv_R8;
			}
			return expr4;
		}
		FieldInfo fieldInfo2 = val.operand as FieldInfo;
		if (val.opcode == OpCodes.Ldfld && fieldInfo2 != null && fieldInfo2.FieldType == typeof(int))
		{
			FieldInfo value3 = null;
			int num4 = -1;
			if (fieldInfo2.Name == "stack" && Behaviors.TryGetValue(owner, out value3) && cursor >= 0 && codes[cursor].opcode == OpCodes.Ldarg_0)
			{
				num4 = cursor--;
			}
			else if (Cached.TryGetValue(fieldInfo2, out value3) && cursor >= 1 && codes[cursor].opcode == OpCodes.Ldflda && codes[cursor - 1].opcode == OpCodes.Ldarg_0)
			{
				num4 = cursor - 1;
				cursor -= 2;
			}
			if (value3 != null && num4 >= 0)
			{
				Count count2 = new Count();
				count2.Item = value3;
				count2.Key = fieldInfo2.ToString();
				count2.Load = codes.GetRange(num4, num - num4 + 1).Select(Clone).ToList();
				value2 = count2;
				Expr expr5 = new Expr();
				expr5.Count = value2;
				expr5.Slope = 1.0;
				expr5.Start = num4;
				return expr5;
			}
		}
		if (val.opcode != OpCodes.Add && val.opcode != OpCodes.Sub && val.opcode != OpCodes.Mul && val.opcode != OpCodes.Div)
		{
			return null;
		}
		Expr expr6 = Parse(codes, ref cursor, locals, owner, depth + 1);
		Expr expr7 = Parse(codes, ref cursor, locals, owner, depth + 1);
		if (expr7 == null || expr6 == null || (expr7.Count != null && expr6.Count != null && expr7.Count.Key != expr6.Count.Key))
		{
			return null;
		}
		Expr expr8 = new Expr();
		expr8.Count = expr7.Count ?? expr6.Count;
		expr8.Start = expr7.Start;
		expr8.Floating = expr7.Floating || expr6.Floating;
		expr8.Double = expr7.Double || expr6.Double;
		Expr expr9 = expr8;
		if (val.opcode == OpCodes.Add)
		{
			expr9.Slope = expr7.Slope + expr6.Slope;
			expr9.Offset = expr7.Offset + expr6.Offset;
		}
		else if (val.opcode == OpCodes.Sub)
		{
			expr9.Slope = expr7.Slope - expr6.Slope;
			expr9.Offset = expr7.Offset - expr6.Offset;
		}
		else if (val.opcode == OpCodes.Mul)
		{
			if (expr7.Slope != 0.0 && expr6.Slope != 0.0)
			{
				return null;
			}
			expr9.Slope = expr7.Slope * expr6.Offset + expr6.Slope * expr7.Offset;
			expr9.Offset = expr7.Offset * expr6.Offset;
		}
		else
		{
			if (expr6.Slope != 0.0 || expr6.Offset == 0.0)
			{
				return null;
			}
			expr9.Slope = expr7.Slope / expr6.Offset;
			expr9.Offset = expr7.Offset / expr6.Offset;
		}
		return expr9;
	}

	private static int ReferenceStart(List<CodeInstruction> codes, int end, int depth)
	{
		if (end < 0 || depth > 5)
		{
			return -1;
		}
		CodeInstruction val = codes[end];
		if (val.opcode == OpCodes.Ldarg_0 || val.opcode == OpCodes.Ldarg_1 || val.opcode == OpCodes.Ldarg_2 || val.opcode == OpCodes.Ldarg_3 || val.opcode == OpCodes.Ldarg || val.opcode == OpCodes.Ldarg_S || Local(val, store: false) >= 0)
		{
			return end;
		}
		if (val.opcode == OpCodes.Ldfld || val.opcode == OpCodes.Ldflda)
		{
			return ReferenceStart(codes, end - 1, depth + 1);
		}
		MethodInfo methodInfo = val.operand as MethodInfo;
		if (methodInfo != null && !methodInfo.IsStatic && methodInfo.GetParameters().Length == 0 && methodInfo.IsSpecialName)
		{
			return ReferenceStart(codes, end - 1, depth + 1);
		}
		return -1;
	}

	private static CodeInstruction Clone(CodeInstruction c)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		return new CodeInstruction(c.opcode, c.operand);
	}
}
internal static class ChestLootManager
{
	private sealed class OptionState
	{
		internal int Total;

		internal int Index;

		internal OptionState Previous;
	}

	[HarmonyPatch(typeof(ChestBehavior), "BaseItemDrop")]
	private static class MultiDrop
	{
		private static void Prefix(ChestBehavior __instance)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (DifficultyManager.Server && Rules.Enabled(Module.Loot) && !(__instance.currentPickup.pickupIndex == PickupIndex.none) && __instance.dropCount >= 1 && !fixedSingle)
			{
				__instance.dropCount = Count();
			}
		}
	}

	[HarmonyPatch(typeof(ChestBehavior), "BaseItemOrbSpawn")]
	private static class PhysicalDrops
	{
		private static bool Prefix(ChestBehavior __instance)
		{
			if (!DifficultyManager.Server || !Rules.Enabled(Module.Loot))
			{
				return true;
			}
			AccessTools.Method(typeof(ChestBehavior), "BaseItemDrop", (Type[])null, (Type[])null).Invoke(__instance, null);
			return false;
		}
	}

	[HarmonyPatch(typeof(OptionChestBehavior), "ItemDrop")]
	private static class OptionDrops
	{
		private static void Prefix(OptionChestBehavior __instance, out OptionState __state)
		{
			__state = null;
			if (DifficultyManager.Server && Rules.Enabled(Module.Loot) && option == null && AccessTools.Field(typeof(OptionChestBehavior), "generatedPickups").GetValue(__instance) is List<UniquePickup> { Count: not 0 })
			{
				__state = new OptionState
				{
					Total = Count(),
					Previous = option
				};
				option = __state;
			}
		}

		private static void Postfix(OptionChestBehavior __instance, OptionState __state)
		{
			if (__state == null)
			{
				return;
			}
			try
			{
				for (int i = 1; i < __state.Total; i++)
				{
					__state.Index = i;
					__instance.Roll();
					__instance.ItemDrop();
				}
			}
			finally
			{
				option = __state.Previous;
			}
		}

		private static Exception Finalizer(Exception __exception, OptionState __state)
		{
			if (__state != null)
			{
				option = __state.Previous;
			}
			return __exception;
		}
	}

	[HarmonyPatch(typeof(PickupDropletController), "CreatePickupDroplet", new Type[]
	{
		typeof(CreatePickupInfo),
		typeof(Vector3),
		typeof(Vector3)
	})]
	private static class OptionSpread
	{
		private static void Prefix(CreatePickupInfo __0, ref Vector3 __1, ref Vector3 __2)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if (option != null && __0.pickerOptions != null && option.Total > 1)
			{
				Quaternion val = Quaternion.AngleAxis(360f * (float)option.Index / (float)option.Total, Vector3.up);
				__1 += val * Vector3.forward * 0.7f;
				__2 = val * __2;
			}
		}
	}

	[HarmonyPatch(typeof(ChestBehavior), "DelusionItemDrop", new Type[] { typeof(DelusionChestController) })]
	private static class DelusionDrops
	{
		private static void Prefix(DelusionChestController __0, out int __state)
		{
			__state = ((DifficultyManager.Server && Rules.Enabled(Module.Loot) && Object.op_Implicit((Object)(object)__0) && __0.isDelusionSelected && __0.IsSelectedCorrectly()) ? Count() : 0);
		}

		private static void Postfix(ChestBehavior __instance, int __state)
		{
			ExtraDelusionDrops(__instance, __state);
		}
	}

	[HarmonyPatch(typeof(RouletteChestController), "EjectPickupServer")]
	private static class RouletteDrops
	{
		private static void Prefix(RouletteChestController __instance, UniquePickup __0, out int __state)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			__state = 0;
			if (DifficultyManager.Server && Rules.Enabled(Module.Loot) && !rouletteExtra && !((UniquePickup)(ref __0)).Equals(UniquePickup.none))
			{
				__state = Count();
				__instance.dropCount = 1;
			}
		}

		private static void Postfix(RouletteChestController __instance, int __state)
		{
			//IL_00aa: 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_002b: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (__state <= 1)
			{
				return;
			}
			rouletteExtra = true;
			try
			{
				Xoroshiro128Plus val = (Xoroshiro128Plus)AccessTools.Field(typeof(RouletteChestController), "rng").GetValue(__instance);
				for (int i = 1; i < __state; i++)
				{
					UniquePickup val2 = __instance.dropTable.GeneratePickup(val);
					Quaternion rotation = __instance.ejectionTransform.rotation;
					try
					{
						__instance.ejectionTransform.rotation = Quaternion.AngleAxis(360f * (float)i / (float)__state, Vector3.up) * rotation;
						AccessTools.Method(typeof(RouletteChestController), "EjectPickupServer", (Type[])null, (Type[])null).Invoke(__instance, new object[1] { val2 });
					}
					finally
					{
						__instance.ejectionTransform.rotation = rotation;
					}
				}
			}
			finally
			{
				rouletteExtra = false;
			}
		}
	}

	[ThreadStatic]
	private static bool fixedSingle;

	[ThreadStatic]
	private static OptionState option;

	[ThreadStatic]
	private static bool rouletteExtra;

	private static int Count()
	{
		NoLimitsConfig settings = NoLimitsPlugin.Settings;
		return RandomSource.Inclusive(Math.Min(settings.ChestDropMin.Value, settings.ChestDropMax.Value), Math.Max(settings.ChestDropMin.Value, settings.ChestDropMax.Value));
	}

	private static void ExtraDelusionDrops(ChestBehavior chest, int count)
	{
		if (count <= 1)
		{
			return;
		}
		bool flag = fixedSingle;
		fixedSingle = true;
		try
		{
			for (int i = 1; i < count; i++)
			{
				chest.Roll();
				chest.dropCount = 1;
				AccessTools.Method(typeof(ChestBehavior), "BaseItemDrop", (Type[])null, (Type[])null).Invoke(chest, null);
			}
		}
		finally
		{
			fixedSingle = flag;
		}
	}
}
internal static class ChestSpawnManager
{
	[HarmonyPatch(typeof(ClassicStageInfo), "RebuildCards")]
	private static class ChestCards
	{
		private static void Prefix(ref DirectorCardCategorySelection __1)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Expected O, but got Unknown
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			if (!DifficultyManager.Server || !Rules.Enabled(Module.Chests) || !DifficultyManager.Stage || !Object.op_Implicit((Object)(object)__1) || !ContentPool.Ready)
			{
				return;
			}
			DirectorCardCategorySelection val = ScriptableObject.CreateInstance<DirectorCardCategorySelection>();
			val.CopyFrom(__1);
			val.categories = (Category[])val.categories.Clone();
			int num = val.FindCategoryIndexByName("Chests");
			if (num < 0)
			{
				num = val.AddCategory("Chests", 1f);
			}
			HashSet<SpawnCard> hashSet = new HashSet<SpawnCard>();
			Category[] categories = val.categories;
			for (int i = 0; i < categories.Length; i++)
			{
				Category val2 = categories[i];
				DirectorCard[] cards = val2.cards;
				foreach (DirectorCard val3 in cards)
				{
					hashSet.Add(val3.GetSpawnCard());
				}
			}
			List<DirectorCard> list = new List<DirectorCard>(ContentPool.Chests);
			list.AddRange(QualityCompatibility.ChestCards);
			foreach (DirectorCard item in list)
			{
				string name = ((Object)item.GetSpawnCard()).name;
				int num2;
				switch (name)
				{
				default:
					num2 = ((name == "iscHollowChest") ? 1 : 0);
					break;
				case "iscChest1":
				case "iscChest2":
				case "iscEquipmentBarrel":
				case "iscCategoryChestDamage":
				case "iscCategoryChestHealing":
				case "iscCategoryChestUtility":
				case "iscCategoryChest2Damage":
				case "iscCategoryChest2Healing":
				case "iscCategoryChest2Utility":
				case "iscLunarChest":
				case "iscVoidChest":
				case "iscCasinoChest":
					num2 = 1;
					break;
				}
				bool flag = (byte)num2 != 0;
				bool flag2 = name == "iscGoldChest" && NoLimitsPlugin.Settings.AllowLegendaryChestsEverywhere.Value;
				if ((flag || flag2 || QualityCompatibility.IsQualityChest(item.GetSpawnCard())) && item.IsAvailable() && hashSet.Add(item.GetSpawnCard()))
				{
					val.AddCard(num, item);
				}
			}
			OwnedSelection ownedSelection = (Object.op_Implicit((Object)(object)ClassicStageInfo.instance) ? ((Component)ClassicStageInfo.instance).gameObject.AddComponent<OwnedSelection>() : null);
			if (Object.op_Implicit((Object)(object)ownedSelection))
			{
				ownedSelection.Selection = val;
			}
			Dictionary<SpawnCard, SpawnCard> dictionary = new Dictionary<SpawnCard, SpawnCard>();
			for (int k = 0; k < val.categories.Length; k++)
			{
				DirectorCard[] array = (DirectorCard[])val.categories[k].cards.Clone();
				for (int l = 0; l < array.Length; l++)
				{
					DirectorCard val4 = array[l];
					SpawnCard spawnCard = val4.GetSpawnCard();
					if (!Object.op_Implicit((Object)(object)spawnCard) || !Object.op_Implicit((Object)(object)spawnCard.prefab) || (!Object.op_Implicit((Object)(object)spawnCard.prefab.GetComponent<ChestBehavior>()) && !Object.op_Implicit((Object)(object)spawnCard.prefab.GetComponent<OptionChestBehavior>()) && !Object.op_Implicit((Object)(object)spawnCard.prefab.GetComponent<RouletteChestController>())))
					{
						continue;
					}
					if (!dictionary.TryGetValue(spawnCard, out var value))
					{
						value = Object.Instantiate<SpawnCard>(spawnCard);
						((Object)value).name = ((Object)spawnCard).name;
						value.directorCreditCost = Math.Max(1, (int)Math.Ceiling((double)spawnCard.directorCreditCost / (double)NoLimitsPlugin.Settings.ChestCreditMultiplier.Value));
						dictionary.Add(spawnCard, value);
						if (Object.op_Implicit((Object)(object)ownedSelection))
						{
							ownedSelection.Cards.Add(value);
						}
					}
					int num3 = l;
					DirectorCard val5 = new DirectorCard();
					val5.spawnCard = value;
					val5.selectionWeight = val4.selectionWeight;
					val5.minimumStageCompletions = val4.minimumStageCompletions;
					val5.spawnDistance = val4.spawnDistance;
					val5.preventOverhead = val4.preventOverhead;
					val5.requiredUnlockableDef = val4.requiredUnlockableDef;
					val5.forbiddenUnlockableDef = val4.forbiddenUnlockableDef;
					array[num3] = val5;
				}
				val.categories[k].cards = array;
			}
			__1 = val;
		}
	}

	private sealed class OwnedSelection : MonoBehaviour
	{
		internal DirectorCardCategorySelection Selection;

		internal readonly List<SpawnCard> Cards = new List<SpawnCard>();

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)Selection))
			{
				Object.Destroy((Object)(object)Selection);
			}
			foreach (SpawnCard card in Cards)
			{
				if (Object.op_Implicit((Object)(object)card))
				{
					Object.Destroy((Object)(object)card);
				}
			}
		}
	}

	internal static void Install()
	{
	}

	internal static void Uninstall()
	{
	}
}
internal static class ContentPool
{
	internal static readonly HashSet<string> BossBodies = new HashSet<string>(StringComparer.Ordinal)
	{
		"BeetleQueen2Body", "VagrantBody", "TitanBody", "ClayBossBody", "MagmaWormBody", "ElectricWormBody", "ImpBossBody", "GravekeeperBody", "RoboBallBossBody", "GrandParentBody",
		"MegaConstructBody", "ScavBody", "VoidMegaCrabBody"
	};

	private static readonly HashSet<string> MonsterBodies = new HashSet<string>(StringComparer.Ordinal)
	{
		"BeetleBody", "BeetleGuardBody", "LemurianBody", "LemurianBruiserBody", "WispBody", "GreaterWispBody", "GolemBody", "BellBody", "BisonBody", "ImpBody",
		"ClayBruiserBody", "ClayGrenadierBody", "JellyfishBody", "MiniMushroomBody", "ParentBody", "RoboBallMiniBody", "VultureBody", "HermitCrabBody", "GupBody", "GipBody",
		"GeepBody", "VerminBody", "FlyingVerminBody", "VoidBarnacleBody", "VoidJailerBody", "LunarGolemBody", "LunarWispBody", "LunarExploderBody", "ChildBody"
	};

	internal static readonly List<DirectorCard> Cards = new List<DirectorCard>();

	internal static readonly List<DirectorCard> Chests = new List<DirectorCard>();

	internal static readonly Dictionary<string, string> Sources = new Dictionary<string, string>(StringComparer.Ordinal);

	private static readonly string[] StoryBodies = new string[8] { "Brother", "VoidRaidCrab", "FalseSonBoss", "SolusWing", "SolusHeart", "Providence", "ScavLunar", "ReaperMalachiteBoss" };

	private static readonly HashSet<string> SpecialScenes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
	{
		"moon", "moon2", "voidraid", "meridian", "solutionalhaunt", "solusweb", "computationalexchange", "limbo", "arena", "goldshores",
		"artifactworld", "champrush", "sanctum"
	};

	private static readonly List<AsyncOperationHandle> Handles = new List<AsyncOperationHandle>();

	internal static bool Ready;

	internal static CharacterBody Body(SpawnCard card)
	{
		if (!Object.op_Implicit((Object)(object)card) || !Object.op_Implicit((Object)(object)card.prefab))
		{
			return null;
		}
		CharacterMaster component = card.prefab.GetComponent<CharacterMaster>();
		if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.bodyPrefab))
		{
			return null;
		}
		return component.bodyPrefab.GetComponent<CharacterBody>();
	}

	internal static bool IsOrdinaryBoss(SpawnCard card)
	{
		CharacterBody val = Body(card);
		if (Object.op_Implicit((Object)(object)val))
		{
			return BossBodies.Contains(((Object)val).name);
		}
		return false;
	}

	internal static bool TeleporterEligible(DirectorCard card)
	{
		SpawnCard spawnCard = card.GetSpawnCard();
		CharacterSpawnCard val = (CharacterSpawnCard)(object)((spawnCard is CharacterSpawnCard) ? spawnCard : null);
		if (Object.op_Implicit((Object)(object)val) && !val.forbiddenAsBoss && IsOrdinaryBoss((SpawnCard)(object)val))
		{
			return card.IsAvailable();
		}
		return false;
	}

	internal static IEnumerator Load()
	{
		HashSet<string> keys = new HashSet<string>(StringComparer.Ordinal);
		HashSet<string> stageCards = new HashSet<string>(StringComparer.Ordinal);
		List<string> stages = (from val7 in (IEnumerable<SceneDef>)(object)SceneCatalog.allSceneDefs
			where Object.op_Implicit((Object)(object)val7) && (int)val7.sceneType == 1 && !val7.isFinalStage && !SpecialScenes.Contains(val7.baseSceneName) && (val7.validForRandomSelection || (val7.stageOrder >= 1 && val7.stageOrder <= 5))
			select val7.baseSceneName).Distinct().ToList();
		foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators)
		{
			foreach (object key2 in resourceLocator.Keys)
			{
				string s = key2 as string;
				if (s != null && s.StartsWith("RoR2/", StringComparison.Ordinal) && s.EndsWith(".asset", StringComparison.Ordinal))
				{
					if (s.IndexOf("/csc", StringComparison.OrdinalIgnoreCase) >= 0 || s.IndexOf("/isc", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						keys.Add(s);
					}
					if ((s.IndexOf("/dccs", StringComparison.OrdinalIgnoreCase) >= 0 || s.IndexOf("/dp", StringComparison.OrdinalIgnoreCase) >= 0) && s.IndexOf("Monsters", StringComparison.OrdinalIgnoreCase) >= 0 && s.IndexOf("UNUSED", StringComparison.OrdinalIgnoreCase) < 0 && stages.Any((string stage) => s.IndexOf("/" + stage + "/", StringComparison.OrdinalIgnoreCase) >= 0))
					{
						stageCards.Add(s);
					}
				}
			}
		}
		HashSet<string> seenBodies = new HashSet<string>();
		HashSet<string> seenChest = new HashSet<string>();
		foreach (string key in keys.OrderBy<string, string>((string result) => result, StringComparer.Ordinal))
		{
			AsyncOperationHandle<SpawnCard> handle = Addressables.LoadAssetAsync<SpawnCard>((object)key);
			yield return handle;
			Handles.Add(AsyncOperationHandle<SpawnCard>.op_Implicit(handle));
			if ((int)handle.Status != 1 || !Object.op_Implicit((Object)(object)handle.Result))
			{
				continue;
			}
			SpawnCard spawn = handle.Result;
			CharacterBody body = Body(spawn);
			bool specialized = ((Object)spawn).name.IndexOf("Karma", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)spawn).name.IndexOf("Barrage", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)spawn).name.IndexOf("Gold", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)spawn).name.IndexOf("LunarScav", StringComparison.OrdinalIgnoreCase) >= 0;
			if (Object.op_Implicit((Object)(object)body) && !specialized && (BossBodies.Contains(((Object)body).name) || MonsterBodies.Contains(((Object)body).name)) && seenBodies.Add(((Object)body).name))
			{
				if (((Object)spawn).name.IndexOf("Gold", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)spawn).name.IndexOf("LunarScav", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					seenBodies.Remove(((Object)body).name);
					continue;
				}
				List<DirectorCard> cards = Cards;
				DirectorCard val = new DirectorCard();
				val.spawnCard = spawn;
				val.selectionWeight = 1;
				val.minimumStageCompletions = 0;
				val.spawnDistance = (MonsterSpawnDistance)0;
				cards.Add(val);
			}
			if (Object.op_Implicit((Object)(object)spawn.prefab) && (Object.op_Implicit((Object)(object)spawn.prefab.GetComponent<ChestBehavior>()) || Object.op_Implicit((Object)(object)spawn.prefab.GetComponent<OptionChestBehavior>()) || Object.op_Implicit((Object)(object)spawn.prefab.GetComponent<RouletteChestController>())) && seenChest.Add(((Object)spawn).name))
			{
				List<DirectorCard> chests = Chests;
				DirectorCard val2 = new DirectorCard();
				val2.spawnCard = spawn;
				val2.selectionWeight = 1;
				val2.minimumStageCompletions = 0;
				chests.Add(val2);
			}
		}
		foreach (string address in stageCards.OrderBy<string, string>((string result) => result, StringComparer.Ordinal))
		{
			if (address.IndexOf("/dccs", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				AsyncOperationHandle<DirectorCardCategorySelection> handle2 = Addressables.LoadAssetAsync<DirectorCardCategorySelection>((object)address);
				yield return handle2;
				Handles.Add(AsyncOperationHandle<DirectorCardCategorySelection>.op_Implicit(handle2));
				if ((int)handle2.Status == 1)
				{
					AddStageSelection(handle2.Result, address, seenBodies);
				}
				continue;
			}
			AsyncOperationHandle<DccsPool> handle3 = Addressables.LoadAssetAsync<DccsPool>((object)address);
			yield return handle3;
			Handles.Add(AsyncOperationHandle<DccsPool>.op_Implicit(handle3));
			if ((int)handle3.Status != 1 || !Object.op_Implicit((Object)(object)handle3.Result))
			{
				continue;
			}
			Category[] poolCategories = handle3.Result.poolCategories;
			foreach (Category val3 in poolCategories)
			{
				if (val3.alwaysIncluded != null)
				{
					PoolEntry[] alwaysIncluded = val3.alwaysIncluded;
					foreach (PoolEntry val4 in alwaysIncluded)
					{
						AddStageSelection(val4.dccs, address, seenBodies);
					}
				}
				if (val3.includedIfConditionsMet != null)
				{
					ConditionalPoolEntry[] includedIfConditionsMet = val3.includedIfConditionsMet;
					foreach (ConditionalPoolEntry val5 in includedIfConditionsMet)
					{
						AddStageSelection(((PoolEntry)val5).dccs, address, seenBodies);
					}
				}
				if (val3.includedIfNoConditionsMet != null)
				{
					PoolEntry[] includedIfNoConditionsMet = val3.includedIfNoConditionsMet;
					foreach (PoolEntry val6 in includedIfNoConditionsMet)
					{
						AddStageSelection(val6.dccs, address, seenBodies);
					}
				}
			}
		}
		Ready = true;
		NoLimitsPlugin.Log.LogInfo((object)("Discovered " + Cards.Count + " allowlisted ordinary enemy cards, " + Chests.Count + " chest cards."));
		foreach (DirectorCard card in Cards)
		{
			NoLimitsPlugin.Log.LogInfo((object)("POOL " + ((Object)Body(card.GetSpawnCard())).name + " / " + ((Object)card.GetSpawnCard()).name + " boss=" + IsOrdinaryBoss(card.GetSpawnCard())));
		}
	}

	private static void AddStageSelection(DirectorCardCategorySelection selection, string address, HashSet<string> seen)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Expected O, but got Unknown
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)selection) || selection.categories == null)
		{
			return;
		}
		Category[] categories = selection.categories;
		for (int i = 0; i < categories.Length; i++)
		{
			Category val = categories[i];
			DirectorCard[] cards = val.cards;
			foreach (DirectorCard val2 in cards)
			{
				if (val2 == null)
				{
					continue;
				}
				SpawnCard spawnCard = val2.GetSpawnCard();
				CharacterSpawnCard val3 = (CharacterSpawnCard)(object)((spawnCard is CharacterSpawnCard) ? spawnCard : null);
				CharacterBody body = Body((SpawnCard)(object)val3);
				if (Object.op_Implicit((Object)(object)body) && !StoryBodies.Any((string prefix) => ((Object)body).name.StartsWith(prefix, StringComparison.Ordinal)) && ((Object)val3).name.IndexOf("Karma", StringComparison.OrdinalIgnoreCase) < 0 && ((Object)val3).name.IndexOf("Barrage", StringComparison.OrdinalIgnoreCase) < 0 && ((Object)val3).name.IndexOf("Gold", StringComparison.OrdinalIgnoreCase) < 0)
				{
					if (body.isChampion)
					{
						BossBodies.Add(((Object)body).name);
					}
					else
					{
						MonsterBodies.Add(((Object)body).name);
					}
					if (!Sources.ContainsKey(((Object)body).name))
					{
						Sources[((Object)body).name] = address;
					}
					if (seen.Add(((Object)body).name))
					{
						List<DirectorCard> cards2 = Cards;
						DirectorCard val4 = new DirectorCard();
						val4.spawnCard = (SpawnCard)(object)val3;
						val4.selectionWeight = 1;
						val4.minimumStageCompletions = 0;
						val4.spawnDistance = val2.spawnDistance;
						val4.preventOverhead = val2.preventOverhead;
						val4.requiredUnlockable = val2.requiredUnlockable;
						val4.forbiddenUnlockable = val2.forbiddenUnlockable;
						val4.requiredUnlockableDef = val2.requiredUnlockableDef;
						val4.forbiddenUnlockableDef = val2.forbiddenUnlockableDef;
						cards2.Add(val4);
						NoLimitsPlugin.Log.LogInfo((object)("ALLOW body=" + ((Object)body).name + " card=" + ((Object)val3).name + " source=" + address));
					}
				}
			}
		}
	}

	internal static void Dispose()
	{
		//IL_000f: 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)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		foreach (AsyncOperationHandle handle in Handles)
		{
			AsyncOperationHandle current = handle;
			if (((AsyncOperationHandle)(ref current)).IsValid())
			{
				Addressables.Release(current);
			}
		}
		Handles.Clear();
		Cards.Clear();
		Chests.Clear();
		Ready = false;
	}
}
internal static class ContinuousItemRules
{
	[HarmonyPatch(typeof(Inventory), "CalculateEquipmentCooldownScale")]
	private static class GearCooldown
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			int power = 0;
			MethodInfo pow = AccessTools.Method(typeof(Mathf), "Pow", new Type[2]
			{
				typeof(float),
				typeof(float)
			}, (Type[])null);
			foreach (CodeInstruction code in input)
			{
				if (CodeInstructionExtensions.Calls(code, pow))
				{
					power++;
					if (power <= 2)
					{
						code.opcode = OpCodes.Call;
						code.operand = AccessTools.Method(typeof(ContinuousItemRules), (power == 1) ? "GearPower" : "GesturePower", (Type[])null, (Type[])null);
					}
				}
				yield return code;
			}
			if (power != 3)
			{
				throw new InvalidOperationException("Equipment cooldown formula changed: " + power);
			}
		}
	}

	[HarmonyPatch(typeof(CharacterBody), "RecalculateStats")]
	private static class Skills
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input, ILGenerator generator)
		{
			List<CodeInstruction> codes = input.ToList();
			Dictionary<int, string> counts = new Dictionary<int, string>();
			Dictionary<int, List<CodeInstruction>> before = new Dictionary<int, List<CodeInstruction>>();
			Dictionary<int, List<CodeInstruction>> after = new Dictionary<int, List<CodeInstruction>>();
			for (int i = 1; i + 1 < codes.Count; i++)
			{
				FieldInfo fieldInfo = codes[i - 1].operand as FieldInfo;
				MethodInfo methodInfo = codes[i].operand as MethodInfo;
				int num = AffineItemRules.LocalIndex(codes[i + 1], store: true);
				if (fieldInfo != null && fieldInfo.FieldType == typeof(ItemDef) && methodInfo != null && methodInfo.DeclaringType == typeof(Inventory) && methodInfo.Name == "GetItemCountEffective" && num >= 0)
				{
					counts[num] = fieldInfo.Name;
				}
			}
			for (int j = 2; j < codes.Count; j++)
			{
				if (codes[j].opcode != OpCodes.Blt && codes[j].opcode != OpCodes.Blt_S)
				{
					continue;
				}
				int num2 = AffineItemRules.LocalIndex(codes[j - 1], store: false);
				if (num2 < 0 || !counts.TryGetValue(num2, out var value) || (value != "AlienHead" && value != "HalfAttackSpeedHalfCooldowns"))
				{
					continue;
				}
				Label label = (Label)codes[j].operand;
				int num3 = codes.FindIndex((CodeInstruction c) => c.labels.Contains(label));
				if (num3 < 0)
				{
					continue;
				}
				float num4 = ((value == "AlienHead") ? 0.75f : 0.5f);
				for (int num5 = num3; num5 < j; num5++)
				{
					if (codes[num5].opcode == OpCodes.Ldc_R4 && Math.Abs((float)codes[num5].operand - num4) < 1E-05f)
					{
						after[num5] = new List<CodeInstruction>
						{
							new CodeInstruction(OpCodes.Ldloc, (object)(short)num2),
							new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "LoopFactor", (Type[])null, (Type[])null))
						};
						before[j] = new List<CodeInstruction>
						{
							new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "LoopBound", (Type[])null, (Type[])null))
						};
						break;
					}
				}
			}
			MethodInfo clamp = AccessTools.Method(typeof(Mathf), "Clamp", new Type[3]
			{
				typeof(float),
				typeof(float),
				typeof(float)
			}, (Type[])null);
			for (int i2 = 0; i2 < codes.Count; i2++)
			{
				if (codes[i2].opcode == OpCodes.Ldc_R4)
				{
					float num6 = (float)codes[i2].operand;
					string skillItem = ((Math.Abs(num6 - 2f / 3f) < 1E-06f) ? "UtilitySkillMagazine" : ((Math.Abs(num6 - 0.67f) < 1E-06f) ? "EquipmentMagazineVoid" : null));
					int num7 = ((skillItem == null) ? (-1) : (from p in counts
						where p.Value == skillItem
						select p.Key).DefaultIfEmpty(-1).First());
					if (num7 >= 0)
					{
						after[i2] = new List<CodeInstruction>
						{
							new CodeInstruction(OpCodes.Ldloc, (object)(short)num7),
							new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "LoopFactor", (Type[])null, (Type[])null))
						};
					}
				}
				if (CodeInstructionExtensions.Calls(codes[i2], clamp) && codes.Skip(Math.Max(0, i2 - 5)).Take(Math.Min(5, i2)).Any((CodeInstruction c) => c.operand is FieldInfo && ((FieldInfo)c.operand).Name == "minCooldownCoefficient"))
				{
					LocalBuilder localBuilder = generator.DeclareLocal(typeof(float));
					LocalBuilder localBuilder2 = generator.DeclareLocal(typeof(float));
					LocalBuilder localBuilder3 = generator.DeclareLocal(typeof(float));
					before[i2] = new List<CodeInstruction>
					{
						new CodeInstruction(OpCodes.Stloc, (object)localBuilder),
						new CodeInstruction(OpCodes.Stloc, (object)localBuilder2),
						new CodeInstruction(OpCodes.Dup, (object)null),
						new CodeInstruction(OpCodes.Stloc, (object)localBuilder3),
						new CodeInstruction(OpCodes.Ldloc, (object)localBuilder2),
						new CodeInstruction(OpCodes.Ldloc, (object)localBuilder)
					};
					after[i2] = new List<CodeInstruction>
					{
						new CodeInstruction(OpCodes.Ldloc, (object)localBuilder3),
						new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "Unclamp", (Type[])null, (Type[])null))
					};
				}
				if (before.TryGetValue(i2, out var insert))
				{
					foreach (CodeInstruction item in insert)
					{
						yield return item;
					}
				}
				yield return codes[i2];
				if (!after.TryGetValue(i2, out insert))
				{
					continue;
				}
				foreach (CodeInstruction item2 in insert)
				{
					yield return item2;
				}
			}
		}
	}

	[HarmonyPatch]
	private static class Convergence
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(HoldoutZoneController).GetNestedType("FocusConvergenceController", BindingFlags.NonPublic), "DoUpdate", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			foreach (CodeInstruction c in input)
			{
				yield return c;
				if (c.operand is FieldInfo && ((FieldInfo)c.operand).Name == "cap")
				{
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "Cap", (Type[])null, (Type[])null));
				}
			}
		}
	}

	[HarmonyPatch]
	private static class Corpsebloom
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(HealthComponent).GetNestedType("RepeatHealComponent", BindingFlags.NonPublic), "RecalculateStats", (Type[])null, (Type[])null);
		}

		private static void Postfix(object __instance)
		{
			if (Active)
			{
				Type type = __instance.GetType();
				object? value = AccessTools.Field(type, "body").GetValue(__instance);
				CharacterBody val = (CharacterBody)((value is CharacterBody) ? value : null);
				if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.inventory))
				{
					AccessTools.Field(type, "healthFractionToRestorePerSecond").SetValue(__instance, 0.1f * (float)Math.Max(1, val.inventory.GetItemCountEffective(Items.RepeatHeal)));
				}
			}
		}
	}

	[HarmonyPatch(typeof(DroneShockDamageBodyBehavior), "get_duration")]
	private static class ShockAura
	{
		private static void Postfix(DroneShockDamageBodyBehavior __instance, ref float __result)
		{
			if (Active)
			{
				__result = 15f / (float)Math.Max(1, ((BaseItemBodyBehavior)__instance).stack);
			}
		}
	}

	[HarmonyPatch(typeof(CharacterBody), "AddTimedBuff", new Type[]
	{
		typeof(BuffDef),
		typeof(float)
	})]
	private static class Stealth
	{
		private static void Prefix(CharacterBody __instance, BuffDef __0, ref float __1)
		{
			if (!Active)
			{
				return;
			}
			if ((Object)(object)__0 == (Object)(object)Buffs.Nullified)
			{
				__1 = NativeProcOverflow.RootDuration(__1);
			}
			else
			{
				if (!Object.op_Implicit((Object)(object)__instance.inventory))
				{
					return;
				}
				if ((Object)(object)__0 == (Object)(object)Buffs.LowHealthOrbSpawnerCooldown)
				{
					__1 /= Math.Max(1, __instance.inventory.GetItemCountEffective(Items.LowHealthOrbSpawner));
				}
				else if (!((Object)(object)__0 != (Object)(object)Buffs.PhasingCooldown))
				{
					int itemCountEffective = __instance.inventory.GetItemCountEffective(Items.Phasing);
					if (itemCountEffective > 0)
					{
						__1 = 35f / (float)itemCountEffective;
					}
				}
			}
		}
	}

	[HarmonyPatch(typeof(LunarSunBehavior), "GetMaxProjectiles")]
	private static class OrbitCount
	{
		private static void Postfix(Inventory __0, ref int __result)
		{
			if (Active)
			{
				__result = (int)Math.Min(2147483647L, 3L * (long)__0.GetItemCountEffective(Items.LunarSun));
			}
		}
	}

	[HarmonyPatch(typeof(AttackSpeedPerNearbyCollider), "UpdateValues")]
	private static class NearbyCapacity
	{
		private static void Postfix(AttackSpeedPerNearbyCollider __instance, int __0)
		{
			if (Active)
			{
				AccessTools.Field(typeof(AttackSpeedPerNearbyCollider), "maxCharacterCount").SetValue(__instance, (int)Math.Min(2147483647L, 3L * (long)Math.Max(0, __0)));
			}
		}
	}

	[HarmonyPatch]
	private static class HyperbolicProcCurves
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(GlobalEventManager), "ProcessHitEnemy", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(SetStateOnHurt), "OnTakeDamageServer", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input, MethodBase __originalMethod)
		{
			MethodInfo conversion = AccessTools.Method(typeof(Util), "ConvertAmplificationPercentageIntoReductionPercentage", (Type[])null, (Type[])null);
			bool stun = __originalMethod.DeclaringType == typeof(SetStateOnHurt);
			bool scaled = false;
			foreach (CodeInstruction code in input)
			{
				if (CodeInstructionExtensions.Calls(code, conversion))
				{
					if (stun)
					{
						yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null);
					}
					code.opcode = OpCodes.Call;
					code.operand = AccessTools.Method(typeof(ContinuousItemRules), stun ? "StunChance" : "RawChance", (Type[])null, (Type[])null);
				}
				MethodInfo call = code.operand as MethodInfo;
				if (stun && !scaled && call != null && call.DeclaringType == typeof(SetStateOnHurt) && call.Name == "SetStun")
				{
					yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "StunDuration", (Type[])null, (Type[])null));
					scaled = true;
				}
				yield return code;
			}
		}
	}

	[HarmonyPatch(typeof(HealthComponent), "TakeDamageProcess")]
	private static class ArmorPlate
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input, ILGenerator generator)
		{
			List<CodeInstruction> codes = input.ToList();
			MethodInfo max = AccessTools.Method(typeof(Mathf), "Max", new Type[2]
			{
				typeof(float),
				typeof(float)
			}, (Type[])null);
			for (int i = 0; i < codes.Count; i++)
			{
				bool plate = CodeInstructionExtensions.Calls(codes[i], max) && codes.Skip(Math.Max(0, i - 9)).Take(Math.Min(9, i)).Any((CodeInstruction c) => c.operand is FieldInfo && ((FieldInfo)c.operand).Name == "armorPlate");
				LocalBuilder raw = null;
				if (plate)
				{
					raw = generator.DeclareLocal(typeof(float));
					yield return new CodeInstruction(OpCodes.Dup, (object)null);
					yield return new CodeInstruction(OpCodes.Stloc, (object)raw);
				}
				yield return codes[i];
				if (plate)
				{
					yield return new CodeInstruction(OpCodes.Ldloc, (object)raw);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "FlatPlate", (Type[])null, (Type[])null));
				}
			}
		}
	}

	[HarmonyPatch(typeof(GoldTitanManager), "TryStartChannelingTitansServer")]
	private static class Titan
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			MethodInfo pow = AccessTools.Method(typeof(Mathf), "Pow", new Type[2]
			{
				typeof(float),
				typeof(float)
			}, (Type[])null);
			foreach (CodeInstruction c in input)
			{
				if (CodeInstructionExtensions.Calls(c, pow))
				{
					c.opcode = OpCodes.Call;
					c.operand = AccessTools.Method(typeof(ContinuousItemRules), "TitanPower", (Type[])null, (Type[])null);
				}
				yield return c;
			}
		}
	}

	[HarmonyPatch(typeof(CharacterBody), "RemoveBuffInternal")]
	private static class Medkit
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			bool medkit = false;
			foreach (CodeInstruction c in input)
			{
				FieldInfo f = c.operand as FieldInfo;
				if (f != null && f.DeclaringType == typeof(Items) && f.Name == "Medkit")
				{
					medkit = true;
				}
				yield return c;
				if (medkit && c.opcode == OpCodes.Ldc_R4 && (float)c.operand == 20f)
				{
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "MedkitFlat", (Type[])null, (Type[])null));
					medkit = false;
				}
			}
		}
	}

	[HarmonyPatch(typeof(DotController), "InflictDot", new Type[]
	{
		typeof(GameObject),
		typeof(GameObject),
		typeof(HurtBox),
		typeof(ProcChainMask),
		typeof(DotIndex),
		typeof(float),
		typeof(float),
		typeof(uint?)
	})]
	private static class GuaranteedBleed
	{
		private static void Prefix(GameObject __1, DotIndex __4, ref float __6)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			DamageInfo currentInfo = NativeProcOverflow.CurrentInfo;
			if (Active && DifficultyManager.Server && (int)__4 == 0 && currentInfo != null && !((Object)(object)currentInfo.attacker != (Object)(object)__1) && Object.op_Implicit((Object)(object)__1))
			{
				CharacterBody component = __1.GetComponent<CharacterBody>();
				if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.inventory) && (DamageTypeCombo.op_Implicit(currentInfo.damageType & DamageTypeCombo.op_Implicit((DamageType)1024)) != 0 || (currentInfo.crit && component.inventory.GetItemCountEffective(Items.BleedOnHitAndExplode) > 0)))
				{
					__6 *= NativeProcOverflow.ActivationCount(nativeResult: true, component.bleedChance * currentInfo.procCoefficient, component.master);
				}
			}
		}
	}

	[HarmonyPatch(typeof(MushroomBodyBehavior), "FixedUpdate")]
	private static class MushroomRadius
	{
		private static void Postfix(MushroomBodyBehavior __instance)
		{
			if (Active && DifficultyManager.Server && ((BaseItemBodyBehavior)__instance).stack > 1)
			{
				object? value = AccessTools.Field(typeof(MushroomBodyBehavior), "mushroomHealingWard").GetValue(__instance);
				HealingWard val = (HealingWard)((value is HealingWard) ? value : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					val.Networkradius += 1.5f * (float)(((BaseItemBodyBehavior)__instance).stack - 1);
				}
			}
		}
	}

	[HarmonyPatch(typeof(IcicleAuraController), "get_maxIcicleCount")]
	private static class IcicleMaximum
	{
		private static void Postfix(IcicleAuraController __instance, ref int __result)
		{
			if (Active && Object.op_Implicit((Object)(object)__instance.owner))
			{
				CharacterBody component = __instance.owner.GetComponent<CharacterBody>();
				if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.inventory))
				{
					int itemCountEffective = component.inventory.GetItemCountEffective(Items.Icicle);
					__result = (int)Math.Min(2147483647L, __result + (long)Math.Max(0, itemCountEffective - 1) * (long)(__instance.baseIcicleMax - __instance.icicleMaxPerStack));
				}
			}
		}
	}

	[HarmonyPatch(typeof(OnLevelUpFreeUnlockBehavior), "LevelThresholdCheck")]
	private static class BondLifetime
	{
		private static bool Prefix()
		{
			return !Active;
		}
	}

	[HarmonyPatch(typeof(CharacterMaster), "GiveMoneyWithOnLevelUpFreeUnlock")]
	private static class BondScaling
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			bool scaling = false;
			foreach (CodeInstruction c in input)
			{
				if (c.opcode == OpCodes.Conv_U8)
				{
					c.opcode = OpCodes.Call;
					c.operand = AccessTools.Method(typeof(ContinuousItemRules), "BondExperience", (Type[])null, (Type[])null);
				}
				yield return c;
				FieldInfo field = c.operand as FieldInfo;
				if (field != null && field.DeclaringType == typeof(CharacterMaster) && field.Name == "maxStacks")
				{
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "StackCap", (Type[])null, (Type[])null));
				}
				if (field != null && field.DeclaringType == typeof(CharacterMaster) && field.Name == "stackingBonus")
				{
					scaling = true;
				}
				if (scaling && c.opcode == OpCodes.Add)
				{
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "BondFactor", (Type[])null, (Type[])null));
					scaling = false;
				}
			}
		}
	}

	[HarmonyPatch(typeof(CharacterBody), "AddFreeChestBuff")]
	private static class BondUnlocks
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			foreach (CodeInstruction c in input)
			{
				yield return c;
				if (c.opcode == OpCodes.Ldc_I4_3)
				{
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "Cap", (Type[])null, (Type[])null));
				}
			}
		}
	}

	[HarmonyPatch(typeof(LowHealthOrbSpawnerBehavior), "GetRollChanceNormalized")]
	private static class RestorationChance
	{
		private static void Postfix(LowHealthOrbSpawnerBehavior __instance, ref float __result)
		{
			if (Active)
			{
				__result = 0.1f * (float)((BaseItemBodyBehavior)__instance).stack;
			}
		}
	}

	[HarmonyPatch(typeof(LowHealthOrbSpawnerBehavior), "ProcessRestoration")]
	private static class RestorationCost
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			List<CodeInstruction> codes = input.ToList();
			int found = 0;
			for (int i = 0; i < codes.Count; i++)
			{
				yield return codes[i];
				if (codes[i].opcode == OpCodes.Ldc_I4 && (int)codes[i].operand == int.MaxValue && i + 1 < codes.Count && codes[i + 1].operand is MethodInfo && ((MethodInfo)codes[i + 1].operand).Name == "set_maxToTransform")
				{
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "ConsumeOne", (Type[])null, (Type[])null));
					found++;
				}
			}
			if (found != 1)
			{
				throw new InvalidOperationException("Dream Crucible consume boundary changed: " + found);
			}
		}
	}

	private static bool Active
	{
		get
		{
			if (DifficultyManager.Active)
			{
				return Rules.Enabled(Module.Items);
			}
			return false;
		}
	}

	internal static void Install()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		RecalculateStatsAPI.GetStatCoefficients += new StatHookEventHandler(Stats);
	}

	internal static void Uninstall()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		RecalculateStatsAPI.GetStatCoefficients -= new StatHookEventHandler(Stats);
	}

	private static void Stats(CharacterBody body, StatHookEventArgs args)
	{
		if (Active && Object.op_Implicit((Object)(object)body.inventory))
		{
			ItemDef[] array = (ItemDef[])(object)new ItemDef[3]
			{
				Items.AttackSpeedOnCrit,
				Items.HealOnCrit,
				Items.BleedOnHitAndExplode
			};
			foreach (ItemDef val in array)
			{
				args.critAdd += 5f * (float)Math.Max(0, body.inventory.GetItemCountEffective(val) - 1);
			}
			if (body.HasBuff(Buffs.CloakSpeed))
			{
				args.moveSpeedMultAdd += 0.4f * (float)Math.Max(0, body.inventory.GetItemCountEffective(Items.Phasing) - 1);
			}
		}
	}

	internal static float LinearCooldown(float basis, float stacks)
	{
		if (!Active)
		{
			return Mathf.Pow(basis, stacks);
		}
		if (stacks <= 0f)
		{
			return 1f;
		}
		return (float)(1.0 / (1.0 + (1.0 - (double)basis) / (double)basis * (double)stacks));
	}

	private static float GearPower(float basis, float stacks)
	{
		return LinearCooldown(basis, stacks);
	}

	private static float GesturePower(float basis, float exponent)
	{
		if (!Active)
		{
			return Mathf.Pow(basis, exponent);
		}
		return 2f / (Math.Max(0f, exponent) + 2f);
	}

	private static float LoopFactor(float basis, int stacks)
	{
		if (!Active)
		{
			return basis;
		}
		return LinearCooldown(basis, stacks);
	}

	private static int LoopBound(int count)
	{
		if (!Active)
		{
			return count;
		}
		if (count <= 0)
		{
			return 0;
		}
		return 1;
	}

	private static float Unclamp(float original, float raw)
	{
		if (!Active || float.IsNaN(raw) || float.IsInfinity(raw))
		{
			return original;
		}
		return Math.Max(0f, raw);
	}

	private static int Cap(int cap)
	{
		if (!Active)
		{
			return cap;
		}
		return int.MaxValue;
	}

	private static float FlatPlate(float original, float raw)
	{
		if (!Active)
		{
			return original;
		}
		return Math.Max(0f, raw);
	}

	private static float RawChance(float percent)
	{
		if (!Active)
		{
			return Util.ConvertAmplificationPercentageIntoReductionPercentage(percent);
		}
		return percent;
	}

	private static float StunChance(float percent, DamageReport report)
	{
		if (!Active)
		{
			return Util.ConvertAmplificationPercentageIntoReductionPercentage(percent);
		}
		if (report != null && Object.op_Implicit((Object)(object)report.attackerMaster) && Object.op_Implicit((Object)(object)report.attackerMaster.inventory) && Object.op_Implicit((Object)(object)report.victim))
		{
			int itemCountEffective = report.attackerMaster.inventory.GetItemCountEffective(Items.VileCenser);
			if (itemCountEffective > 1)
			{
				percent += 25f * (float)(itemCountEffective - 1) * (1f - Mathf.Clamp01(report.victim.combinedHealthFraction)) * report.damageInfo.procCoefficient;
			}
		}
		return percent;
	}

	private static float StunDuration(float duration, DamageReport report)
	{
		if (!Active || report == null || !Object.op_Implicit((Object)(object)report.attackerMaster) || !Object.op_Implicit((Object)(object)report.attackerMaster.inventory))
		{
			return duration;
		}
		Inventory inventory = report.attackerMaster.inventory;
		float num = 5f * (float)inventory.GetItemCountEffective(Items.StunChanceOnHit);
		if (Object.op_Implicit((Object)(object)report.victim))
		{
			num += 25f * (float)inventory.GetItemCountEffective(Items.VileCenser) * (1f - Mathf.Clamp01(report.victim.combinedHealthFraction));
		}
		num *= report.damageInfo.procCoefficient;
		return duration * (float)NativeProcOverflow.ActivationCount(nativeResult: true, num, report.attackerMaster);
	}

	private static float TitanPower(float basis, float exponent)
	{
		if (!Active || exponent != 0.5f)
		{
			return Mathf.Pow(basis, exponent);
		}
		return basis;
	}

	private static int ConsumeOne(int original)
	{
		if (!Active)
		{
			return original;
		}
		return 1;
	}

	private static float MedkitFlat(float original, CharacterBody body)
	{
		if (!Active || !Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.inventory))
		{
			return original;
		}
		return original * (float)Math.Max(1, body.inventory.GetItemCountEffective(Items.Medkit));
	}

	private static uint StackCap(uint original)
	{
		if (!Active)
		{
			return original;
		}
		return uint.MaxValue;
	}

	private static float BondFactor(float original, CharacterMaster master)
	{
		if (!Active || !Object.op_Implicit((Object)(object)master) || !Object.op_Implicit((Object)(object)master.inventory) || master.inventory.GetItemCountEffective(Items.OnLevelUpFreeUnlock) <= 0)
		{
			return original;
		}
		return 0.12f * (float)master.inventory.GetItemCountEffective(Items.OnLevelUpFreeUnlock);
	}

	internal static ulong BondExperience(double value)
	{
		if (!Active)
		{
			return (ulong)value;
		}
		if (double.IsNaN(value) || value <= 0.0)
		{
			return 0uL;
		}
		if (!(value >= 1.8446744073709552E+19))
		{
			return (ulong)value;
		}
		return ulong.MaxValue;
	}
}
internal static class DeathMarkRule
{
	private sealed class AppliedMark : MonoBehaviour
	{
		internal int Stacks;
	}

	[HarmonyPatch(typeof(GlobalEventManager), "ProcDeathMark")]
	private static class Applied
	{
		private static void Prefix(CharacterBody victimBody, out bool __state)
		{
			__state = Object.op_Implicit((Object)(object)victimBody) && victimBody.HasBuff(Buffs.DeathMark);
		}

		private static void Postfix(CharacterBody victimBody, CharacterMaster attackerMaster, bool __state)
		{
			if (DifficultyManager.Server && Rules.Enabled(Module.Items) && !__state && Object.op_Implicit((Object)(object)victimBody) && Object.op_Implicit((Object)(object)attackerMaster) && Object.op_Implicit((Object)(object)attackerMaster.inventory) && victimBody.HasBuff(Buffs.DeathMark))
			{
				AppliedMark appliedMark = ((Component)victimBody).GetComponent<AppliedMark>();
				if (!Object.op_Implicit((Object)(object)appliedMark))
				{
					appliedMark = ((Component)victimBody).gameObject.AddComponent<AppliedMark>();
				}
				appliedMark.Stacks = attackerMaster.inventory.GetItemCountEffective(Items.DeathMark);
			}
		}
	}

	[HarmonyPatch(typeof(HealthComponent), "TakeDamageProcess")]
	private static class Damage
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			bool mark = false;
			int found = 0;
			foreach (CodeInstruction code in input)
			{
				FieldInfo field = code.operand as FieldInfo;
				if (field != null && field.DeclaringType == typeof(Buffs) && field.Name == "DeathMark")
				{
					mark = true;
				}
				yield return code;
				if (mark && code.opcode == OpCodes.Ldc_R4 && (float)code.operand == 1.5f)
				{
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DeathMarkRule), "Factor", (Type[])null, (Type[])null));
					mark = false;
					found++;
				}
			}
			if (found != 1)
			{
				throw new InvalidOperationException("Death Mark damage anchor changed: " + found);
			}
		}
	}

	internal static float Factor(float original, HealthComponent target)
	{
		if (!DifficultyManager.Server || !Rules.Enabled(Module.Items) || !Object.op_Implicit((Object)(object)target))
		{
			return original;
		}
		AppliedMark component = ((Component)target).GetComponent<AppliedMark>();
		return original + 0.5f * (float)Math.Max(0, Object.op_Implicit((Object)(object)component) ? (component.Stacks - 1) : 0);
	}
}
internal static class DeferredEffects
{
	internal delegate void Effect(object[] args, object[] locals);

	private sealed class Job
	{
		internal int Remaining;

		internal Effect Action;

		internal object[] Args;

		internal object[] Locals;

		internal DamageInfo Info;

		internal CharacterBody Attacker;

		internal int Stage;

		internal bool World;
	}

	private static readonly List<Effect> Actions = new List<Effect>();

	private static readonly Queue<Job> Jobs = new Queue<Job>();

	private static int frame = -1;

	private static int spent;

	internal static long Pending;

	private static int Budget => NoLimitsPlugin.Settings.ExtraProcBudgetPerFrame.Value;

	private static void NewFrame()
	{
		if (frame != Time.frameCount)
		{
			frame = Time.frameCount;
			spent = 0;
		}
	}

	internal static int Inline(int count)
	{
		NewFrame();
		int num = Math.Min(Math.Max(0, count - 1), Math.Max(0, Budget - spent));
		spent += num;
		if (count <= 0)
		{
			return 0;
		}
		return num + 1;
	}

	internal static void Enqueue(int id, int remaining, object[] args, object[] locals)
	{
		if (remaining > 0)
		{
			DamageInfo val = args.OfType<DamageInfo>().FirstOrDefault();
			DamageReport val2 = args.OfType<DamageReport>().FirstOrDefault();
			if (val == null && val2 != null)
			{
				val = val2.damageInfo;
			}
			CharacterBody attacker = ((val != null && Object.op_Implicit((Object)(object)val.attacker)) ? val.attacker.GetComponent<CharacterBody>() : null);
			Jobs.Enqueue(new Job
			{
				Action = Actions[id],
				Remaining = remaining,
				Args = args,
				Locals = locals,
				Info = val,
				Attacker = attacker,
				Stage = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.stageClearCount : 0)
			});
			Pending += remaining;
		}
	}

	internal static void Schedule(Effect action, int count, object[] args, DamageInfo info)
	{
		if (count > 0 && info != null && Object.op_Implicit((Object)(object)info.attacker))
		{
			Jobs.Enqueue(new Job
			{
				Action = action,
				Remaining = count,
				Args = args,
				Locals = new object[0],
				Info = info,
				Attacker = info.attacker.GetComponent<CharacterBody>(),
				Stage = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.stageClearCount : 0)
			});
			Pending += count;
		}
	}

	internal static void ScheduleWorld(Effect action, int count, object[] args)
	{
		if (count > 0 && Object.op_Implicit((Object)(object)Run.instance))
		{
			Jobs.Enqueue(new Job
			{
				Action = action,
				Remaining = count,
				Args = args,
				Locals = new object[0],
				Stage = Run.instance.stageClearCount,
				World = true
			});
			Pending += count;
		}
	}

	internal static void Tick()
	{
		if (!DifficultyManager.Server || !Rules.Enabled(Module.Items))
		{
			Clear();
			return;
		}
		NewFrame();
		while (Jobs.Count > 0 && spent < Budget)
		{
			Job job = Jobs.Dequeue();
			if ((!job.World && !Object.op_Implicit((Object)(object)job.Attacker)) || !Object.op_Implicit((Object)(object)Run.instance) || job.Stage != Run.instance.stageClearCount)
			{
				Pending -= job.Remaining;
				continue;
			}
			spent++;
			job.Remaining--;
			Pending--;
			NativeProcOverflow.Frame frame = NativeProcOverflow.EnterDeferred(job.Info);
			try
			{
				job.Action(job.Args, job.Locals);
			}
			catch (Exception ex)
			{
				NoLimitsPlugin.Log.LogError((object)("Deferred native effect failed; remaining branch cancelled: " + ex));
				Pending -= job.Remaining;
				job.Remaining = 0;
			}
			finally
			{
				NativeProcOverflow.ExitDeferred(frame);
			}
			if (job.Remaining > 0)
			{
				Jobs.Enqueue(job);
			}
		}
	}

	internal static void Clear()
	{
		Jobs.Clear();
		Pending = 0L;
	}

	private static int Argument(CodeInstruction c)
	{
		if (c.opcode == OpCodes.Ldarg_0)
		{
			return 0;
		}
		if (c.opcode == OpCodes.Ldarg_1)
		{
			return 1;
		}
		if (c.opcode == OpCodes.Ldarg_2)
		{
			return 2;
		}
		if (c.opcode == OpCodes.Ldarg_3)
		{
			return 3;
		}
		if (c.opcode != OpCodes.Ldarg && c.opcode != OpCodes.Ldarg_S && c.opcode != OpCodes.Ldarga && c.opcode != OpCodes.Ldarga_S && c.opcode != OpCodes.Starg && c.opcode != OpCodes.Starg_S)
		{
			return -1;
		}
		if (c.operand is ParameterInfo { Position: var position } parameterInfo)
		{
			return position + ((!((MethodBase)parameterInfo.Member).IsStatic) ? 1 : 0);
		}
		return Convert.ToInt32(c.operand);
	}

	private static int Local(CodeInstruction c)
	{
		int num = AffineItemRules.LocalIndex(c, store: false);
		if (num >= 0)
		{
			return num;
		}
		num = AffineItemRules.LocalIndex(c, store: true);
		if (num >= 0)
		{
			return num;
		}
		if (c.opcode != OpCodes.Ldloca && c.opcode != OpCodes.Ldloca_S)
		{
			return -1;
		}
		if (c.operand is LocalBuilder localBuilder)
		{
			return localBuilder.LocalIndex;
		}
		if (c.operand is LocalVariableInfo localVariableInfo)
		{
			return localVariableInfo.LocalIndex;
		}
		return Convert.ToInt32(c.operand);
	}

	internal static Type[] LocalTypes(MethodBase method, List<CodeInstruction> codes)
	{
		Dictionary<int, Type> dictionary = method.GetMethodBody().LocalVariables.ToDictionary((LocalVariableInfo v) => v.LocalIndex, (LocalVariableInfo v) => v.LocalType);
		foreach (CodeInstruction code in codes)
		{
			if (code.operand is LocalBuilder localBuilder)
			{
				dictionary[localBuilder.LocalIndex] = localBuilder.LocalType;
			}
		}
		int num = ((dictionary.Count == 0) ? (-1) : dictionary.Keys.Max());
		Type[] array = new Type[num + 1];
		for (int num2 = 0; num2 < array.Length; num2++)
		{
			array[num2] = (dictionary.ContainsKey(num2) ? dictionary[num2] : typeof(object));
		}
		if (array.Any((Type t) => t.IsByRef || t.IsPointer || t == typeof(TypedReference)))
		{
			throw new InvalidOperationException("Unboxable proc local in " + method.Name);
		}
		return array;
	}

	internal static Type[] ArgumentTypes(MethodBase method)
	{
		List<Type> list = new List<Type>();
		if (!method.IsStatic)
		{
			list.Add(method.DeclaringType);
		}
		list.AddRange(from p in method.GetParameters()
			select p.ParameterType);
		return list.ToArray();
	}

	internal static int Compile(MethodBase method, List<CodeInstruction> codes, int start, int end, Type[] types)
	{
		DynamicMethod dynamicMethod = new DynamicMethod("NoLimitsDeferred_" + method.Name + "_" + Actions.Count, typeof(void), new Type[2]
		{
			typeof(object[]),
			typeof(object[])
		}, typeof(DeferredEffects).Module, skipVisibility: true);
		ILGenerator il = dynamicMethod.GetILGenerator();
		LocalBuilder[] array = types.Select((Type t) => il.DeclareLocal(t)).ToArray();
		Type[] array2 = ArgumentTypes(method);
		LocalBuilder[] array3 = array2.Select((Type t) => il.DeclareLocal(t)).ToArray();
		for (int num = 0; num < array.Length; num++)
		{
			il.Emit(OpCodes.Ldarg_1);
			il.Emit(OpCodes.Ldc_I4, num);
			il.Emit(OpCodes.Ldelem_Ref);
			il.Emit(OpCodes.Unbox_Any, types[num]);
			il.Emit(OpCodes.Stloc, array[num]);
		}
		for (int num2 = 0; num2 < array3.Length; num2++)
		{
			il.Emit(OpCodes.Ldarg_0);
			il.Emit(OpCodes.Ldc_I4, num2);
			il.Emit(OpCodes.Ldelem_Ref);
			il.Emit(OpCodes.Unbox_Any, array2[num2]);
			il.Emit(OpCodes.Stloc, array3[num2]);
		}
		Label exit = il.DefineLabel();
		Dictionary<Label, Label> labels = new Dictionary<Label, Label>();
		for (int num3 = start; num3 < end; num3++)
		{
			foreach (Label label in codes[num3].labels)
			{
				if (!labels.ContainsKey(label))
				{
					labels[label] = il.DefineLabel();
				}
			}
		}
		for (int num4 = start; num4 < end; num4++)
		{
			CodeInstruction val = codes[num4];
			foreach (Label label2 in val.labels)
			{
				il.MarkLabel(labels[label2]);
			}
			if (val.blocks.Count > 0)
			{
				throw new InvalidOperationException("Exception region inside deferred effect " + method.Name);
			}
			int num5 = Argument(val);
			int num6 = Local(val);
			if (num5 >= 0)
			{
				il.Emit((val.opcode == OpCodes.Ldarga || val.opcode == OpCodes.Ldarga_S) ? OpCodes.Ldloca : ((val.opcode == OpCodes.Starg || val.opcode == OpCodes.Starg_S) ? OpCodes.Stloc : OpCodes.Ldloc), array3[num5]);
				continue;
			}
			if (num6 >= 0)
			{
				il.Emit((val.opcode == OpCodes.Ldloca || val.opcode == OpCodes.Ldloca_S) ? OpCodes.Ldloca : ((AffineItemRules.LocalIndex(val, store: true) >= 0) ? OpCodes.Stloc : OpCodes.Ldloc), array[num6]);
				continue;
			}
			if (val.opcode == OpCodes.Ret)
			{
				il.Emit(OpCodes.Br, exit);
				continue;
			}
			object operand = val.operand;
			OpCode opcode = val.opcode;
			if (operand is Label key)
			{
				il.Emit(Long(opcode), labels.ContainsKey(key) ? labels[key] : exit);
				continue;
			}
			if (operand is Label[])
			{
				il.Emit(opcode, ((Label[])operand).Select((Label l) => (!labels.ContainsKey(l)) ? exit : labels[l]).ToArray());
				continue;
			}
			if (operand == null)
			{
				il.Emit(opcode);
				continue;
			}
			if (operand is MethodInfo)
			{
				il.Emit(opcode, (MethodInfo)operand);
				continue;
			}
			if (operand is ConstructorInfo)
			{
				il.Emit(opcode, (ConstructorInfo)operand);
				continue;
			}
			if (operand is FieldInfo)
			{
				il.Emit(opcode, (FieldInfo)operand);
				continue;
			}
			if (operand is Type)
			{
				il.Emit(opcode, (Type)operand);
				continue;
			}
			if (operand is string)
			{
				il.Emit(opcode, (string)operand);
				continue;
			}
			if (operand is float)
			{
				il.Emit(opcode, (float)operand);
				continue;
			}
			if (operand is double)
			{
				il.Emit(opcode, (double)operand);
				continue;
			}
			if (operand is long)
			{
				il.Emit(opcode, (long)operand);
				continue;
			}
			if (operand is sbyte)
			{
				il.Emit(opcode, (sbyte)operand);
				continue;
			}
			if (operand is byte)
			{
				il.Emit(opcode, (byte)operand);
				continue;
			}
			if (operand is short)
			{
				il.Emit(opcode, (short)operand);
				continue;
			}
			if (operand is int)
			{
				il.Emit(opcode, (int)operand);
				continue;
			}
			throw new InvalidOperationException(string.Concat("Unsupported effect operand ", operand.GetType(), " at ", method.Name));
		}
		il.MarkLabel(exit);
		for (int num7 = 0; num7 < array.Length; num7++)
		{
			il.Emit(OpCodes.Ldarg_1);
			il.Emit(OpCodes.Ldc_I4, num7);
			il.Emit(OpCodes.Ldloc, array[num7]);
			if (types[num7].IsValueType)
			{
				il.Emit(OpCodes.Box, types[num7]);
			}
			il.Emit(OpCodes.Stelem_Ref);
		}
		il.Emit(OpCodes.Ret);
		Effect item = (Effect)dynamicMethod.CreateDelegate(typeof(Effect));
		int count = Actions.Count;
		Actions.Add(item);
		return count;
	}

	internal static OpCode Long(OpCode op)
	{
		if (!op.Name.EndsWith(".s", StringComparison.Ordinal))
		{
			return op;
		}
		string b = op.Name.Substring(0, op.Name.Length - 2).Replace('.', '_');
		FieldInfo[] fields = typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public);
		foreach (FieldInfo fieldInfo in fields)
		{
			if (string.Equals(fieldInfo.Name, b, StringComparison.OrdinalIgnoreCase))
			{
				return (OpCode)fieldInfo.GetValue(null);
			}
		}
		return op;
	}

	internal static IEnumerable<CodeInstruction> Snapshot(Type[] args, Type[] locals)
	{
		yield return new CodeInstruction(OpCodes.Ldc_I4, (object)args.Length);
		yield return new CodeInstruction(OpCodes.Newarr, (object)typeof(object));
		for (int i = 0; i < args.Length; i++)
		{
			yield return new CodeInstruction(OpCodes.Dup, (object)null);
			yield return new CodeInstruction(OpCodes.Ldc_I4, (object)i);
			yield return new CodeInstruction(OpCodes.Ldarg, (object)(short)i);
			if (args[i].IsValueType)
			{
				yield return new CodeInstruction(OpCodes.Box, (object)args[i]);
			}
			yield return new CodeInstruction(OpCodes.Stelem_Ref, (object)null);
		}
		yield return new CodeInstruction(OpCodes.Ldc_I4, (object)locals.Length);
		yield return new CodeInstruction(OpCodes.Newarr, (object)typeof(object));
		for (int j = 0; j < locals.Length; j++)
		{
			yield return new CodeInstruction(OpCodes.Dup, (object)null);
			yield return new CodeInstruction(OpCodes.Ldc_I4, (object)j);
			yield return new CodeInstruction(OpCodes.Ldloc, (object)(short)j);
			if (locals[j].IsValueType)
			{
				yield return new CodeInstruction(OpCodes.Box, (object)locals[j]);
			}
			yield return new CodeInstruction(OpCodes.Stelem_Ref, (object)null);
		}
	}
}
internal static class ExecutionOverflowRules
{
	private sealed class Frame
	{
		internal Frame Previous;

		internal int Lens;

		internal bool Used;
	}

	private sealed class Work
	{
		internal Vector3 Position;

		internal GameObject Attacker;

		internal bool EliteOnly;
	}

	[HarmonyPatch(typeof(CharacterBody), "get_executeEliteHealthFraction")]
	private static class Guillotine
	{
		private static void Postfix(CharacterBody __instance, ref float __result)
		{
			if (DifficultyManager.Active && Rules.Enabled(Module.Items) && Object.op_Implicit((Object)(object)__instance.inventory))
			{
				float num = 13f * (float)__instance.inventory.GetItemCountEffective(Items.ExecuteLowHealthElite);
				__result += num / 100f - Util.ConvertAmplificationPercentageIntoReductionPercentage(num) / 100f;
			}
		}
	}

	[HarmonyPatch(typeof(HealthComponent), "TakeDamageProcess")]
	private static class Lens
	{
		private static void Prefix(out Frame __state)
		{
			__state = new Frame
			{
				Previous = current
			};
			current = __state;
		}

		private static Exception Finalizer(Exception __exception, Frame __state)
		{
			if (__state != null)
			{
				current = __state.Previous;
			}
			return __exception;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input, ILGenerator generator)
		{
			bool lens = false;
			int found = 0;
			foreach (CodeInstruction code in input)
			{
				FieldInfo field = code.operand as FieldInfo;
				if (field != null && field.DeclaringType == typeof(Items) && field.Name == "CritGlassesVoid")
				{
					lens = true;
				}
				MethodInfo call = code.operand as MethodInfo;
				if (lens && call != null && call.Name.Contains("g__LocalCheckRoll"))
				{
					LocalBuilder[] arguments = (from p in call.GetParameters()
						select generator.DeclareLocal(p.ParameterType)).ToArray();
					for (int i = arguments.Length - 1; i >= 0; i--)
					{
						yield return new CodeInstruction(OpCodes.Stloc, (object)arguments[i]);
					}
					for (int i2 = 0; i2 < arguments.Length; i2++)
					{
						yield return new CodeInstruction(OpCodes.Ldloc, (object)arguments[i2]);
					}
					yield return code;
					yield return new CodeInstruction(OpCodes.Ldloc, (object)arguments[0]);
					yield return new CodeInstruction(OpCodes.Ldloc, (object)arguments[1]);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ExecutionOverflowRules), "LensRoll", (Type[])null, (Type[])null));
					lens = false;
					found++;
				}
				else
				{
					yield return code;
				}
			}
			if (found != 1)
			{
				throw new InvalidOperationException("Lost Seer roll anchor changed: " + found);
			}
		}
	}

	[ThreadStatic]
	private static Frame current;

	[ThreadStatic]
	private static bool executing;

	internal static int Completed;

	private static bool Active
	{
		get
		{
			if (DifficultyManager.Server)
			{
				return Rules.Enabled(Module.Items);
			}
			return false;
		}
	}

	internal static void Install()
	{
		GlobalEventManager.onServerCharacterExecuted += Executed;
	}

	internal static void Uninstall()
	{
		GlobalEventManager.onServerCharacterExecuted -= Executed;
	}

	private static bool LensRoll(bool original, float chance, CharacterMaster master)
	{
		if (current != null && Active && !executing)
		{
			current.Lens = Math.Max(0, NativeProcOverflow.ActivationCount(original, chance, master) - 1);
		}
		return original;
	}

	private static void Executed(DamageReport report, float lost)
	{
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		if (!Active || executing || current == null || current.Used || report == null || !Object.op_Implicit((Object)(object)report.attackerBody) || !Object.op_Implicit((Object)(object)report.attackerBody.inventory) || !Object.op_Implicit((Object)(object)report.victimBody))
		{
			return;
		}
		current.Used = true;
		int num = current.Lens;
		bool eliteOnly = false;
		if (num == 0 && report.victimBody.isElite)
		{
			int itemCountEffective = report.attackerBody.inventory.GetItemCountEffective(Items.ExecuteLowHealthElite);
			if (itemCountEffective > 0)
			{
				num = Math.Max(0, NativeProcOverflow.ActivationCount(nativeResult: true, 13f * (float)itemCountEffective, report.attackerMaster) - 1);
				eliteOnly = true;
			}
		}
		if (num > 0)
		{
			DeferredEffects.Schedule(Execute, num, new object[1]
			{
				new Work
				{
					Position = report.victimBody.corePosition,
					Attacker = ((Component)report.attackerBody).gameObject,
					EliteOnly = eliteOnly
				}
			}, report.damageInfo);
		}
	}

	private static bool Story(CharacterBody body)
	{
		string name = ((Object)body).name;
		if (!name.StartsWith("Brother", StringComparison.Ordinal) && !name.StartsWith("VoidRaidCrab", StringComparison.Ordinal) && !name.StartsWith("FalseSonBoss", StringComparison.Ordinal) && !name.StartsWith("Providence", StringComparison.Ordinal) && !name.StartsWith("SolusHeart", StringComparison.Ordinal) && !name.StartsWith("SolusWing", StringComparison.Ordinal))
		{
			return name.StartsWith("ScavLunar", StringComparison.Ordinal);
		}
		return true;
	}

	private static void Execute(object[] args, object[] locals)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Expected O, but got Unknown
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Invalid comparison between Unknown and I4
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		Work work = (Work)args[0];
		CharacterBody val = (Object.op_Implicit((Object)(object)work.Attacker) ? work.Attacker.GetComponent<CharacterBody>() : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return;
		}
		CharacterBody val2 = null;
		float value = NoLimitsPlugin.Settings.ExecutionOverflowRadius.Value;
		value *= value;
		TeamMask enemyTeams = TeamMask.GetEnemyTeams(val.teamComponent.teamIndex);
		foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList)
		{
			if (Object.op_Implicit((Object)(object)readOnlyInstances) && Object.op_Implicit((Object)(object)readOnlyInstances.healthComponent) && readOnlyInstances.healthComponent.alive && !readOnlyInstances.healthComponent.godMode && Object.op_Implicit((Object)(object)readOnlyInstances.teamComponent) && ((TeamMask)(ref enemyTeams)).HasTeam(readOnlyInstances.teamComponent.teamIndex) && (int)readOnlyInstances.teamComponent.teamIndex != 0 && (int)readOnlyInstances.teamComponent.teamIndex != 1 && !Story(readOnlyInstances) && (readOnlyInstances.bodyFlags & 0x810) == 0 && !(work.EliteOnly ? (!readOnlyInstances.isElite) : readOnlyInstances.isBoss))
			{
				Vector3 val4 = readOnlyInstances.corePosition - work.Position;
				float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude;
				if (!(sqrMagnitude >= value))
				{
					value = sqrMagnitude;
					val2 = readOnlyInstances;
				}
			}
		}
		if (!Object.op_Implicit((Object)(object)val2))
		{
			return;
		}
		executing = true;
		try
		{
			HealthComponent healthComponent = val2.healthComponent;
			DamageInfo val5 = new DamageInfo();
			val5.attacker = work.Attacker;
			val5.damage = 1f;
			val5.procCoefficient = 0f;
			val5.procChainMask = NativeProcOverflow.CurrentInfo.procChainMask;
			val5.damageType = DamageTypeCombo.op_Implicit((DamageType)327746);
			val5.position = val2.corePosition;
			healthComponent.TakeDamage(val5);
			if (!val2.healthComponent.alive)
			{
				Completed++;
			}
		}
		finally
		{
			executing = false;
		}
	}
}
internal static class ItemStackingManager
{
	[HarmonyPatch(typeof(HealthComponent), "TakeDamageProcess")]
	private static class DamageRules
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			int crit = 0;
			int bear = 0;
			bool voidBear = false;
			MethodInfo pow = AccessTools.Method(typeof(Mathf), "Pow", new Type[2]
			{
				typeof(float),
				typeof(float)
			}, (Type[])null);
			MethodInfo critGetter = AccessTools.PropertyGetter(typeof(CharacterBody), "critMultiplier");
			foreach (CodeInstruction code in input)
			{
				FieldInfo field = code.operand as FieldInfo;
				if (field != null && field.DeclaringType == typeof(Items) && field.Name == "BearVoid")
				{
					voidBear = true;
				}
				if (voidBear && CodeInstructionExtensions.Calls(code, pow))
				{
					code.opcode = OpCodes.Call;
					code.operand = AccessTools.Method(typeof(ItemStackingManager), "VoidBearPower", (Type[])null, (Type[])null);
					bear++;
					if (bear == 2)
					{
						voidBear = false;
					}
				}
				yield return code;
				if (CodeInstructionExtensions.Calls(code, critGetter))
				{
					yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ItemStackingManager), "ApplyCritOverflow", (Type[])null, (Type[])null));
					crit++;
				}
			}
			if (crit != 1 || bear != 2)
			{
				throw new InvalidOperationException("Item IL changed: crit=" + crit + " voidBear=" + bear);
			}
		}
	}

	internal static float OverflowCritMultiplier(CharacterBody attacker)
	{
		return AdjustCrit(attacker.critMultiplier, attacker);
	}

	internal static float AdjustCrit(float original, CharacterBody attacker)
	{
		if (!DifficultyManager.Server || !Rules.Enabled(Module.Items) || attacker.crit <= 100f)
		{
			return original;
		}
		double num = ((double)attacker.crit - 100.0) / 100.0;
		double num2 = Math.Floor(num);
		if (Util.CheckRoll((float)((num - num2) * 100.0), attacker.master))
		{
			num2 += 1.0;
		}
		double val = (double)original + num2 * (double)(original - 1f);
		return (float)Math.Min(3.4028234663852886E+38, val);
	}

	internal static float ApplyCritOverflow(float original, DamageInfo info)
	{
		CharacterBody val = ((info != null && Object.op_Implicit((Object)(object)info.attacker)) ? info.attacker.GetComponent<CharacterBody>() : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return original;
		}
		return AdjustCrit(original, val);
	}

	internal static float VoidBearPower(float basis, float stacks)
	{
		if (!DifficultyManager.Server || !Rules.Enabled(Module.Items))
		{
			return Mathf.Pow(basis, stacks);
		}
		return Mathf.Max(Time.fixedDeltaTime, 13.5f / Mathf.Max(1f, stacks)) / 15f;
	}
}
internal static class LevelScalingManager
{
	[HarmonyPatch(typeof(TeamManager), "GetExperienceForLevel")]
	private static class ExperienceTable
	{
		private static bool Prefix(uint __0, ref ulong __result)
		{
			if (!Extended)
			{
				return true;
			}
			__result = Threshold(__0, XpMultiplier);
			return false;
		}
	}

	[HarmonyPatch(typeof(TeamManager), "FindLevelForExperience")]
	private static class Inverse
	{
		private static bool Prefix(ulong __0, ref uint __result)
		{
			if (!Extended)
			{
				return true;
			}
			__result = Level(__0, XpMultiplier);
			return false;
		}
	}

	[HarmonyPatch(typeof(TeamManager), "SetTeamExperience")]
	private static class RemoveHardCap
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			int count = 0;
			foreach (CodeInstruction code in input)
			{
				yield return code;
				if (CodeInstructionExtensions.LoadsField(code, AccessTools.Field(typeof(TeamManager), "hardExpCap"), false))
				{
					count++;
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(LevelScalingManager), "ExperienceCap", (Type[])null, (Type[])null));
				}
			}
			if (count != 2)
			{
				throw new InvalidOperationException("TeamManager hardExpCap IL changed: " + count);
			}
		}
	}

	[HarmonyPatch(typeof(Run), "RecalculateDifficultyCoefficentInternal")]
	private static class Ambient
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input)
		{
			bool cap = false;
			int count = 0;
			MethodInfo min = AccessTools.Method(typeof(Mathf), "Min", new Type[2]
			{
				typeof(float),
				typeof(float)
			}, (Type[])null);
			foreach (CodeInstruction code in input)
			{
				if (CodeInstructionExtensions.LoadsField(code, AccessTools.Field(typeof(Run), "ambientLevelCap"), false))
				{
					cap = true;
				}
				if (cap && CodeInstructionExtensions.Calls(code, min))
				{
					code.opcode = OpCodes.Call;
					code.operand = AccessTools.Method(typeof(LevelScalingManager), "AmbientClamp", (Type[])null, (Type[])null);
					cap = false;
					count++;
				}
				yield return code;
			}
			if (count != 1)
			{
				throw new InvalidOperationException("Run ambient clamp IL changed: " + count);
			}
		}
	}

	private static bool Extended
	{
		get
		{
			if (DifficultyManager.Active && Rules.Enabled(Module.Levels))
			{
				if (!SettingsSnapshot.Received)
				{
					return NoLimitsPlugin.Settings.RemovePlayerLevelCap.Value;
				}
				return SettingsSnapshot.RemovePlayerCap;
			}
			return false;
		}
	}

	private static float XpMultiplier
	{
		get
		{
			if (!SettingsSnapshot.Received)
			{
				return NoLimitsPlugin.Settings.PlayerXpRequirementMultiplier.Value;
			}
			return SettingsSnapshot.Xp;
		}
	}

	internal static ulong Threshold(uint level, float multiplier)
	{
		decimal num = ((level == 0) ? 0m : ((decimal)level - 1m));
		decimal num2 = decimal.Ceiling((decimal)multiplier * (10m * num * num + 10m * num));
		if (!(num2 >= 18446744073709551615m))
		{
			return (ulong)num2;
		}
		return ulong.MaxValue;
	}

	internal static uint Level(ulong xp, float multiplier)
	{
		uint num = 1u;
		uint num2 = 4294967294u;
		while (num < num2)
		{
			uint num3 = num + (uint)(int)((ulong)((long)num2 - (long)num + 1) / 2uL);
			ulong num4 = Threshold(num3, multiplier);
			if (num4 < ulong.MaxValue && num4 <= xp)
			{
				num = num3;
			}
			else
			{
				num2 = num3 - 1;
			}
		}
		return num;
	}

	internal static ulong ExperienceCap(ulong original)
	{
		if (!Extended)
		{
			return original;
		}
		return ulong.MaxValue;
	}

	internal static float AmbientClamp(float value, float cap)
	{
		if (!DifficultyManager.Active || !Rules.Enabled(Module.Levels))
		{
			return Mathf.Min(value, cap);
		}
		return ScaleAmbientGrowth(value, cap, SettingsSnapshot.Received ? SettingsSnapshot.Enemy : NoLimitsPlugin.Settings.EnemyLevelScalingMultiplier.Value, SettingsSnapshot.Received ? SettingsSnapshot.RemoveEnemyCap : NoLimitsPlugin.Settings.RemoveEnemyLevelCap.Value);
	}

	internal static float ScaleAmbientGrowth(float value, float cap, float multiplier, bool removeCap)
	{
		double num = 1.0 + ((double)value - 1.0) * (double)multiplier;
		double val = (removeCap ? 2147483391.0 : ((double)cap));
		if (double.IsNaN(num))
		{
			num = 1.0;
		}
		return (float)Math.Max(1.0, Math.Min(val, num));
	}
}
internal static class LootOverflowRules
{
	private sealed class ShrineFrame
	{
		internal ShrineFrame Previous;

		internal UniquePickup Pickup;
	}

	private sealed class ShrineWork
	{
		internal PickupDropTable Table;

		internal Xoroshiro128Plus Rng;

		internal Vector3 Position;

		internal Vector3 Velocity;

		internal UniquePickup Original;
	}

	private sealed class ExtraLunarDroplet : MonoBehaviour
	{
	}

	[HarmonyPatch(typeof(ShrineChanceBehavior), "AddShrineStack")]
	private static class ChanceDoll
	{
		private static void Prefix(out ShrineFrame __state)
		{
			__state = new ShrineFrame
			{
				Previous = shrine
			};
			shrine = __state;
		}

		private static void Postfix(ShrineChanceBehavior __instance, Interactor __0, ShrineFrame __state)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			if (!Active || !Object.op_Implicit((Object)(object)__0) || __state.Pickup == UniquePickup.none || !Object.op_Implicit((Object)(object)__instance.chanceDollDropTable) || !(bool)AccessTools.Field(typeof(ShrineChanceBehavior), "chanceDollWin").GetValue(__instance))
			{
				return;
			}
			CharacterBody component = ((Component)__0).GetComponent<CharacterBody>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.inventory))
			{
				int num = NativeProcOverflow.ActivationCount(nativeResult: true, 40f * (float)component.inventory.GetItemCountEffective(Items.ExtraShrineItem), component.master) - 1;
				if (num > 0)
				{
					DeferredEffects.ScheduleWorld(DollDrop, num, new object[1]
					{
						new ShrineWork
						{
							Table = __instance.chanceDollDropTable,
							Rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong),
							Position = __instance.dropletOrigin.position,
							Velocity = __instance.dropletOrigin.forward * 20f,
							Original = __state.Pickup
						}
					});
				}
			}
		}

		private static Exception Finalizer(Exception __exception, ShrineFrame __state)
		{
			if (__state != null)
			{
				shrine = __state.Previous;
			}
			return __exception;
		}
	}

	[HarmonyPatch(typeof(PickupDropletController), "CreatePickupDroplet", new Type[]
	{
		typeof(CreatePickupInfo),
		typeof(Vector3),
		typeof(Vector3)
	})]
	private static class CaptureShrineDrop
	{
		private static void Prefix(CreatePickupInfo __0)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (shrine != null)
			{
				shrine.Pickup = ((CreatePickupInfo)(ref __0)).pickup;
			}
		}
	}

	[HarmonyPatch(typeof(GenericPickupController), "CreatePickup")]
	private static class Eulogy
	{
		private static void Postfix(CreatePickupInfo __0)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (!dropletScope)
			{
				QueueLunar(__0);
			}
		}
	}

	[HarmonyPatch(typeof(PickupDropletController), "OnEnable")]
	private static class TagExtra
	{
		private static void Postfix(PickupDropletController __instance)
		{
			if (lunarExtra && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<ExtraLunarDroplet>()))
			{
				((Component)__instance).gameObject.AddComponent<ExtraLunarDroplet>();
			}
		}
	}

	[HarmonyPatch(typeof(PickupDropletController), "CreatePickup")]
	private static class LandingScope
	{
		private static void Prefix(PickupDropletController __instance, out byte __state)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			__state = (byte)((lunarExtra ? 1 : 0) | (dropletScope ? 2 : 0));
			dropletScope = true;
			lunarExtra |= Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<ExtraLunarDroplet>());
			CreatePickupInfo info = (CreatePickupInfo)AccessTools.Field(typeof(PickupDropletController), "createPickupInfo").GetValue(__instance);
			info.position = ((Component)__instance).transform.position;
			QueueLunar(info);
		}

		private static Exception Finalizer(Exception __exception, byte __state)
		{
			lunarExtra = (__state & 1) != 0;
			dropletScope = (__state & 2) != 0;
			return __exception;
		}
	}

	[ThreadStatic]
	private static ShrineFrame shrine;

	[ThreadStatic]
	private static bool lunarExtra;

	[ThreadStatic]
	private static bool dropletScope;

	internal static int LunarExtras;

	internal static int DollExtras;

	internal static ItemIndex LastLunarExtra = (ItemIndex)(-1);

	private static bool Active
	{
		get
		{
			if (DifficultyManager.Server)
			{
				return Rules.Enabled(Module.Items);
			}
			return false;
		}
	}

	private static void DollDrop(object[] args, object[] locals)
	{
		//IL_0018: Unknown