Decompiled source of Beyond 150 v1.0.2

plugins/Beyond150.dll

Decompiled 16 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LootClicker;
using LootClicker.Entities;
using LootClicker.Entities.Characters;
using LootClicker.Entities.Monsters;
using LootClicker.Entities.Skills;
using LootClicker.Services;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Beyond150")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+185abbc525a82435d08112cf46e76b55a4bf3589")]
[assembly: AssemblyProduct("Beyond 150")]
[assembly: AssemblyTitle("Beyond150")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LootunMyMod
{
	[BepInPlugin("nemonline.lootun.beyond150", "Beyond 150", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		internal static Harmony Harmony;

		internal static ConfigEntry<int> MaxAscendancyLevel;

		internal static ConfigEntry<float> XpGrowthPerLevel;

		internal static ConfigEntry<float> KillXpMultiplier;

		internal static ConfigEntry<int> MaxMasteryLevel;

		internal static ConfigEntry<float> MasteryXpGrowthPerLevel;

		internal static ConfigEntry<int> PassiveMaxRank;

		internal static ConfigEntry<int> ClassPassiveMaxRank;

		internal static ConfigEntry<int> AscLevelsPerClassPoint;

		internal static ConfigEntry<float> ClassRankStep;

		internal static void ApplyPatches()
		{
			int num = 0;
			int num2 = 0;
			foreach (Type item in from t in AccessTools.GetTypesFromAssembly(typeof(Plugin).Assembly)
				orderby (!t.Name.StartsWith("Tasks_") && !t.Name.StartsWith("Points_")) ? 1 : 0
				select t)
			{
				if (!(item == typeof(Locale_SetupLocale_Hook)) && item.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Any())
				{
					try
					{
						Harmony.CreateClassProcessor(item).Patch();
						num++;
					}
					catch (Exception arg)
					{
						num2++;
						Logger.LogError((object)$"Patch {item.Name} failed: {arg}");
					}
				}
			}
			Class_OnOff_Scaling.LogSummary();
			Logger.LogInfo((object)$"Patching done: {num} patch classes applied, {num2} failed");
		}

		private void Awake()
		{
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			MaxAscendancyLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Levels", "MaxAscendancyLevel", 200, "Vanilla 50. Total character level = 100 + this (200 => level 300).");
			XpGrowthPerLevel = ((BaseUnityPlugin)this).Config.Bind<float>("Levels", "XpGrowthPerLevel", 0.0176f, "XP needed per level above 150 = 38M * (1 + this * (level - 150)). 0.0176 matches monster XP growth (same kills per level as at 150 when fighting your level), 0 = flat 38M per level. The vanilla-formula continuation would be ~0.0316.");
			KillXpMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Levels", "KillXpMultiplierAbove150", 1f, "Multiplies XP from kills (character and skill mastery) while a character is above level 150. 2 = twice as fast, 0.5 = longer grind. Levels 1-150 and mission completion rewards are unaffected.");
			MaxMasteryLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Mastery", "MaxMasteryLevel", 40, "Vanilla 30. Max base mastery level for skills (gems/enchants still add on top).");
			MasteryXpGrowthPerLevel = ((BaseUnityPlugin)this).Config.Bind<float>("Mastery", "MasteryXpGrowthPerLevel", 0.063f, "Mastery XP needed above level 30 = XP(29) * (1 + this * (level - 29)), XP(29) ~ 949M. 0.063 ~ continues the vanilla curve, 0 = flat ~949M per level.");
			PassiveMaxRank = ((BaseUnityPlugin)this).Config.Bind<int>("Passives", "PassiveMaxRank", 10, "New max rank for class passives (Warrior/Ranger/Mage/Paladin), generic Ascendancy passives and skill mastery passives. Only passives that are above rank 1 in vanilla are changed; rank-1 modifier passives (e.g. Shared Protection) always stay at 1.");
			ClassPassiveMaxRank = ((BaseUnityPlugin)this).Config.Bind<int>("Passives", "ClassPassiveMaxRank", 5, "New max rank for Ascendancy class passives (Barbarian Passives etc.) whose effect actually scales with rank. On/off passives stay at 1.");
			AscLevelsPerClassPoint = ((BaseUnityPlugin)this).Config.Bind<int>("Passives", "AscendancyLevelsPerClassPoint", 10, "One extra Ascendancy class passive point every N Ascendancy levels above 50.");
			ClassRankStep = ((BaseUnityPlugin)this).Config.Bind<float>("Passives", "ClassPassiveRankStep", 0.5f, "Ascendancy class passives: each rank above 1 adds this fraction of the base value (0.5 => rank 5 = 3x base). Applies to all classes' rank-scaling passives.");
			Harmony = new Harmony("nemonline.lootun.beyond150");
			Harmony.CreateClassProcessor(typeof(Locale_SetupLocale_Hook)).Patch();
			Logger.LogInfo((object)(string.Format("{0} loaded: max level {1}, ", "Beyond 150", 100 + MaxAscendancyLevel.Value) + $"passive rank {PassiveMaxRank.Value}, class passive rank {ClassPassiveMaxRank.Value}"));
		}
	}
	[HarmonyPatch(typeof(Locale), "SetupLocale")]
	internal static class Locale_SetupLocale_Hook
	{
		private static bool done;

		private static void Postfix()
		{
			if (!done)
			{
				done = true;
				Plugin.ApplyPatches();
			}
		}
	}
	internal static class Util
	{
		public const int VanillaAscCap = 50;

		public const int VanillaMasteryCap = 30;

		public const int VanillaLevelCap = 150;

		public static int XpPenaltyLevel(Character c)
		{
			return Math.Min(((Entity)c).Level, 150);
		}

		private static long ScaleKillXp(Character c, long exp)
		{
			if (c == null || ((Entity)c).Level <= 150)
			{
				return exp;
			}
			float num = Math.Max(0f, Plugin.KillXpMultiplier.Value);
			return Math.Max(1L, (long)Math.Round((double)exp * (double)num));
		}

		public static void AddKillExperience(Character c, long exp, bool fromSave)
		{
			c.AddExperience(ScaleKillXp(c, exp), fromSave);
		}

		public static void AddKillSkillExperience(Character c, long exp)
		{
			c.AddSkillExperience(ScaleKillXp(c, exp));
		}

		public static int AscendancyLevelCap()
		{
			if (Tasks.AscendancyLevelCap < 50)
			{
				return Math.Min(Tasks.AscendancyLevelCap, 50);
			}
			return Plugin.MaxAscendancyLevel.Value;
		}

		public static IEnumerable<CodeInstruction> SwapConst(IEnumerable<CodeInstruction> instructions, string where, int from, int to, int expectedHits)
		{
			int hits = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.LoadsConstant(instruction, (long)from))
				{
					hits++;
					yield return new CodeInstruction(OpCodes.Ldc_I4, (object)to)
					{
						labels = instruction.labels,
						blocks = instruction.blocks
					};
				}
				else
				{
					yield return instruction;
				}
			}
			if (hits == expectedHits)
			{
				Plugin.Logger.LogInfo((object)$"{where}: replaced {hits}x {from} -> {to}");
			}
			else
			{
				Plugin.Logger.LogWarning((object)$"{where}: expected {expectedHits}x {from}, found {hits} (game update?)");
			}
		}

		public static int ExtraLevels(Character c)
		{
			if (c == null)
			{
				return 0;
			}
			Ascendancy ascendancy = c.Ascendancy;
			int num = ((ascendancy != null) ? ascendancy.Level : 0);
			if (c.Ascendancies != null)
			{
				foreach (Ascendancy value in c.Ascendancies.Values)
				{
					if (value != null && value.Level > num)
					{
						num = value.Level;
					}
				}
			}
			return Math.Max(0, num - 50);
		}
	}
	internal static class Ranks
	{
		private static readonly HashSet<Passive> Done = new HashSet<Passive>();

		private static readonly Dictionary<AscendancyClass, HashSet<int>> ScalingClassPassives = new Dictionary<AscendancyClass, HashSet<int>>
		{
			{
				(AscendancyClass)1,
				new HashSet<int>
				{
					1, 2, 3, 4, 5, 6, 7, 9, 10, 11,
					13, 14, 15, 16, 17, 18, 19
				}
			},
			{
				(AscendancyClass)12,
				new HashSet<int>
				{
					1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
					11, 14, 16, 18, 19
				}
			},
			{
				(AscendancyClass)2,
				new HashSet<int>
				{
					1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
					11, 12, 13, 14, 15, 16, 17, 18
				}
			},
			{
				(AscendancyClass)3,
				new HashSet<int>
				{
					1, 3, 4, 5, 6, 7, 8, 9, 10, 11,
					12, 13, 15, 16, 18, 20
				}
			},
			{
				(AscendancyClass)4,
				new HashSet<int>
				{
					1, 2, 3, 4, 5, 6, 7, 8, 9, 11,
					12, 13, 14, 15, 16, 17, 18, 19
				}
			},
			{
				(AscendancyClass)5,
				new HashSet<int>
				{
					1, 2, 3, 4, 5, 6, 8, 10, 12, 14,
					16, 17, 20
				}
			},
			{
				(AscendancyClass)6,
				new HashSet<int>
				{
					1, 2, 4, 5, 6, 8, 9, 10, 11, 12,
					13, 14, 15, 17, 19
				}
			},
			{
				(AscendancyClass)7,
				new HashSet<int>
				{
					1, 3, 5, 7, 8, 9, 11, 12, 13, 14,
					15, 16, 20
				}
			},
			{
				(AscendancyClass)8,
				new HashSet<int>
				{
					3, 5, 6, 7, 9, 10, 12, 13, 14, 15,
					16, 17, 18, 20
				}
			},
			{
				(AscendancyClass)9,
				new HashSet<int>
				{
					1, 2, 4, 5, 7, 9, 10, 12, 13, 14,
					16, 17, 18, 19
				}
			},
			{
				(AscendancyClass)10,
				new HashSet<int>
				{
					1, 3, 7, 8, 9, 10, 11, 12, 13, 14,
					15, 16, 19, 20
				}
			},
			{
				(AscendancyClass)11,
				new HashSet<int>
				{
					1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
					11, 12, 13, 14, 15, 16, 18, 19
				}
			}
		};

		public static void Boost(IEnumerable<Passive> passives)
		{
			if (passives == null)
			{
				return;
			}
			int value = Plugin.PassiveMaxRank.Value;
			foreach (Passive passife in passives)
			{
				if (passife != null && Done.Add(passife) && passife.MaxRank > 1 && passife.MaxRank < value)
				{
					passife.MaxRank = value;
				}
			}
		}

		public static bool IsScalingClassPassive(AscendancyClass cls, int id)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (ScalingClassPassives.TryGetValue(cls, out var value))
			{
				return value.Contains(id);
			}
			return false;
		}

		public static void BoostClassPassives(Ascendancy asc)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (((asc != null) ? asc.AscendancyPassives : null) == null || !ScalingClassPassives.TryGetValue(asc.Class, out var value))
			{
				return;
			}
			int value2 = Plugin.ClassPassiveMaxRank.Value;
			for (int i = 0; i < asc.AscendancyPassives.Length; i++)
			{
				Passive val = asc.AscendancyPassives[i];
				if (val != null && value.Contains(i + 1) && Done.Add(val) && val.MaxRank < value2)
				{
					val.MaxRank = value2;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character), "AddExperience")]
	internal static class Character_AddExperience_Cap
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> ins)
		{
			return Util.SwapConst(ins, "Character.AddExperience", 50, Plugin.MaxAscendancyLevel.Value, 1);
		}
	}
	[HarmonyPatch(typeof(Character), "SetupExperience")]
	internal static class Character_SetupExperience_Cap
	{
		private const double XpAt150 = 38000000.0;

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> ins)
		{
			MethodInfo vanillaCap = AccessTools.Method(typeof(Tasks), "GetAscendancyLevelCap", (Type[])null, (Type[])null);
			MethodInfo ourCap = AccessTools.Method(typeof(Util), "AscendancyLevelCap", (Type[])null, (Type[])null);
			int redirected = 0;
			foreach (CodeInstruction item in Util.SwapConst(ins, "Character.SetupExperience", 50, Plugin.MaxAscendancyLevel.Value, 1))
			{
				if (CodeInstructionExtensions.Calls(item, vanillaCap))
				{
					item.operand = ourCap;
					redirected++;
				}
				yield return item;
			}
			Plugin.Logger.LogInfo((object)$"Character.SetupExperience: redirected {redirected}x GetAscendancyLevelCap");
		}

		private static void Postfix(Character __instance)
		{
			if (__instance.CharacterLevel >= 100 && __instance.MaxExperience != int.MaxValue)
			{
				int level = ((Entity)__instance).Level;
				if (level > 150)
				{
					double num = 38000000.0 * (1.0 + (double)(Math.Max(0f, Plugin.XpGrowthPerLevel.Value) * (float)(level - 150)));
					__instance.MaxExperience = ((num >= 2147483646.0) ? 2147483646 : Math.Max(1, (int)num));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Monster), "GrantExperience")]
	internal static class Monster_GrantExperience_Penalty
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo penaltyLevel = AccessTools.Method(typeof(Util), "XpPenaltyLevel", (Type[])null, (Type[])null);
			MethodInfo addXp = AccessTools.Method(typeof(Util), "AddKillExperience", (Type[])null, (Type[])null);
			MethodInfo addSkillXp = AccessTools.Method(typeof(Util), "AddKillSkillExperience", (Type[])null, (Type[])null);
			int level = 0;
			int xp = 0;
			int skillXp = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if ((instruction.opcode == OpCodes.Callvirt || instruction.opcode == OpCodes.Call) && instruction.operand is MethodInfo methodInfo)
				{
					MethodInfo methodInfo2 = ((methodInfo.Name == "get_Level") ? penaltyLevel : ((methodInfo.Name == "AddExperience" && methodInfo.DeclaringType == typeof(Character)) ? addXp : ((methodInfo.Name == "AddSkillExperience" && methodInfo.DeclaringType == typeof(Character)) ? addSkillXp : null)));
					if (methodInfo2 != null)
					{
						if (methodInfo2 == penaltyLevel)
						{
							level++;
						}
						else if (methodInfo2 == addXp)
						{
							xp++;
						}
						else
						{
							skillXp++;
						}
						yield return new CodeInstruction(OpCodes.Call, (object)methodInfo2)
						{
							labels = instruction.labels,
							blocks = instruction.blocks
						};
						continue;
					}
				}
				yield return instruction;
			}
			if (level == 1 && xp == 1 && skillXp == 1)
			{
				Plugin.Logger.LogInfo((object)"Monster.GrantExperience: XP level penalty capped at 150, kill XP multiplier hooked");
			}
			else
			{
				Plugin.Logger.LogWarning((object)$"Monster.GrantExperience: expected 1/1/1 (get_Level/AddExperience/AddSkillExperience), found {level}/{xp}/{skillXp}");
			}
		}
	}
	[HarmonyPatch(typeof(Tasks), "GetAscendancyLevelCap")]
	internal static class Tasks_GetAscendancyLevelCap
	{
		private static void Postfix(ref int __result)
		{
			__result = Util.AscendancyLevelCap();
		}
	}
	[HarmonyPatch(typeof(Character), "SetupPassives")]
	internal static class Character_SetupPassives_Ranks
	{
		private static void Postfix(Character __instance)
		{
			Ranks.Boost((IEnumerable<Passive>)__instance.Passives);
		}
	}
	[HarmonyPatch]
	internal static class Ascendancy_Ctor_Ranks
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return AccessTools.GetDeclaredConstructors(typeof(Ascendancy), (bool?)null);
		}

		private static void Postfix(Ascendancy __instance)
		{
			Ranks.Boost(__instance.GenericPassives);
			Ranks.BoostClassPassives(__instance);
		}
	}
	[HarmonyPatch]
	internal static class Skill_GeneratePassives_Ranks
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from t in typeof(Skill).Assembly.GetTypes()
				where !t.IsAbstract && typeof(Skill).IsAssignableFrom(t)
				select AccessTools.DeclaredMethod(t, "GeneratePassives", (Type[])null, (Type[])null) into m
				where m != null
				select m;
		}

		private static void Postfix(Skill __instance)
		{
			if (!(__instance is FactionCooldown))
			{
				Ranks.Boost(__instance.Passives);
			}
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class Points_Class
	{
		private static void Postfix(Character __instance, ref int __result)
		{
			int num = Util.ExtraLevels(__instance);
			int num2 = num / 5;
			int num3 = num % 5;
			__result += 2 * num2 + ((num3 >= 2) ? 2 : ((num3 >= 1) ? 1 : 0));
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class Points_DefaultAttack
	{
		private static void Postfix(Character __instance, ref int __result)
		{
			int num = Util.ExtraLevels(__instance);
			__result += num / 5 + ((num % 5 >= 3) ? 1 : 0);
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class Points_Offensive
	{
		private static void Postfix(Character __instance, ref int __result)
		{
			int num = Util.ExtraLevels(__instance);
			__result += num / 5 + ((num % 5 >= 4) ? 1 : 0);
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class Points_Defensive
	{
		private static void Postfix(Character __instance, ref int __result)
		{
			__result += Util.ExtraLevels(__instance) / 5;
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class Points_AscendancyClass
	{
		private static void Postfix(Ascendancy __instance, ref int __result)
		{
			int num = __instance.Level - 50;
			if (num > 0)
			{
				__result += num / Math.Max(1, Plugin.AscLevelsPerClassPoint.Value);
			}
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class Points_AscendancyGeneric
	{
		private static void Postfix(Ascendancy __instance, ref int __result)
		{
			int level = __instance.Level;
			__result = ((level > 0) ? (level - Math.Min(level / 5 + 1, 10)) : 0);
		}
	}
	internal static class ClassScaling
	{
		public static double Mult(int rank)
		{
			if (rank > 0)
			{
				return 1.0 + (double)(Plugin.ClassRankStep.Value * (float)(rank - 1));
			}
			return 0.0;
		}

		public static int Rank(Ascendancy asc, int id)
		{
			Passive[] array = ((asc != null) ? asc.AscendancyPassives : null);
			if (array == null || id < 1 || id > array.Length)
			{
				return 0;
			}
			Passive obj = array[id - 1];
			if (obj == null)
			{
				return 0;
			}
			return obj.CurrentRank;
		}

		public static int ScaleByRank(int baseValue, int rank)
		{
			return (int)Math.Round((double)baseValue * Mult(rank));
		}

		public static int ScaleInt(int value, Ascendancy asc, int id)
		{
			return (int)Math.Round((double)value * Mult(Math.Max(1, Rank(asc, id))));
		}

		public static double ScaleDouble(double value, Ascendancy asc, int id)
		{
			return value * Mult(Math.Max(1, Rank(asc, id)));
		}
	}
	[HarmonyPatch]
	internal static class Ascendancy_UpdatePassive_Scaling
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from t in typeof(Ascendancy).Assembly.GetTypes()
				where !t.IsAbstract && t.IsSubclassOf(typeof(Ascendancy))
				select AccessTools.DeclaredMethod(t, "UpdateAscendancyPassive", (Type[])null, (Type[])null) into m
				where m != null
				select m;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			//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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo methodInfo = AccessTools.Method(typeof(ClassScaling), "ScaleByRank", (Type[])null, (Type[])null);
			int num = 0;
			for (int i = 1; i < list.Count - 1; i++)
			{
				if (CodeInstructionExtensions.LoadsConstant(list[i - 1]) && CodeInstructionExtensions.IsLdarg(list[i], (int?)2) && list[i + 1].opcode == OpCodes.Mul)
				{
					list[i + 1] = new CodeInstruction(OpCodes.Call, (object)methodInfo)
					{
						labels = list[i + 1].labels,
						blocks = list[i + 1].blocks
					};
					num++;
				}
			}
			Plugin.Logger.LogInfo((object)$"{original.DeclaringType?.Name}.UpdateAscendancyPassive: {num} rank-scaled value(s)");
			return list;
		}
	}
	internal class ConstSpec
	{
		public Type Class;

		public string Method;

		public int PassiveId;

		public long IntValue;

		public double? DoubleValue;

		public string NextCall;

		public long? NextConst;

		public OpCode? NextOp;

		public bool VarMul;

		public int Occurrence = -1;

		public int Expected = 1;

		public string Label => $"{Class.Name}.{Method}: passive {PassiveId}";

		public bool Matches(List<CodeInstruction> l, int i)
		{
			if (!(DoubleValue.HasValue ? CodeInstructionExtensions.LoadsConstant(l[i], DoubleValue.Value) : CodeInstructionExtensions.LoadsConstant(l[i], IntValue)))
			{
				return false;
			}
			if (NextCall != null)
			{
				if (l[i + 1].operand is MethodInfo methodInfo)
				{
					return methodInfo.Name == NextCall;
				}
				return false;
			}
			if (NextConst.HasValue)
			{
				return CodeInstructionExtensions.LoadsConstant(l[i + 1], NextConst.Value);
			}
			if (NextOp.HasValue)
			{
				return l[i + 1].opcode == NextOp.Value;
			}
			if (VarMul)
			{
				if (i + 2 < l.Count && (CodeInstructionExtensions.IsLdloc(l[i + 1], (LocalBuilder)null) || CodeInstructionExtensions.IsLdarg(l[i + 1], (int?)null)))
				{
					return l[i + 2].opcode == OpCodes.Mul;
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class Class_OnOff_Scaling
	{
		private static readonly OpCode Add = OpCodes.Add;

		private static readonly OpCode Mul = OpCodes.Mul;

		private const string MoreDmg = "AddMoreDamageOverride";

		private const string SetValue = "set_Value";

		private const string Proc = "CheckProc";

		private const string ReduceCd = "ReduceCooldown";

		private const string Stacks = "AddStackValue";

		private static readonly Type Barb = typeof(Barbarian);

		private static readonly Type Temp = typeof(Templar);

		private static readonly Type Jugg = typeof(Juggernaut);

		private static readonly Type Ward = typeof(Warden);

		private static readonly Type Assa = typeof(Assassin);

		private static readonly Type Mark = typeof(Marksman);

		private static readonly Type Rene = typeof(Renegade);

		private static readonly Type Arch = typeof(Archmage);

		private static readonly Type Vizi = typeof(Vizier);

		private static readonly Type Batt = typeof(Battlemage);

		private static readonly Type Crus = typeof(Crusader);

		private static readonly Type Inqu = typeof(Inquisitor);

		private static readonly ConstSpec[] Specs;

		internal static int Mismatches;

		private static readonly Dictionary<(Type, int), string> Notes;

		private static ConstSpec I(Type t, string m, int id, long v, string call = null, long? next = null, OpCode? op = null, bool varMul = false, int occ = -1, int exp = 1)
		{
			return new ConstSpec
			{
				Class = t,
				Method = m,
				PassiveId = id,
				IntValue = v,
				NextCall = call,
				NextConst = next,
				NextOp = op,
				VarMul = varMul,
				Occurrence = occ,
				Expected = exp
			};
		}

		private static ConstSpec D(Type t, string m, int id, double v, int occ = -1, int exp = 1)
		{
			return new ConstSpec
			{
				Class = t,
				Method = m,
				PassiveId = id,
				DoubleValue = v,
				Occurrence = occ,
				Expected = exp
			};
		}

		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in Specs.Select((ConstSpec s) => (Class: s.Class, Method: s.Method)).Distinct().Select<(Type, string), MethodBase>((Func<(Type, string), MethodBase>)(((Type Class, string Method) x) => AccessTools.Method(x.Class, x.Method, (Type[])null, (Type[])null)))
				where m != null
				select m;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Expected O, but got Unknown
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo methodInfo = AccessTools.Method(typeof(ClassScaling), "ScaleInt", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(ClassScaling), "ScaleDouble", (Type[])null, (Type[])null);
			List<(int, ConstSpec)> list2 = new List<(int, ConstSpec)>();
			foreach (ConstSpec item in Specs.Where((ConstSpec s) => s.Class == original.DeclaringType && s.Method == original.Name))
			{
				int num = 0;
				int num2 = 0;
				for (int num3 = 0; num3 < list.Count - 1; num3++)
				{
					if (item.Matches(list, num3) && (item.Occurrence < 0 || num++ == item.Occurrence))
					{
						list2.Add((num3, item));
						num2++;
					}
				}
				if (num2 == item.Expected)
				{
					Plugin.Logger.LogDebug((object)(item.Label + " now rank-scaling"));
					continue;
				}
				Mismatches++;
				Plugin.Logger.LogWarning((object)$"{item.Label} expected {item.Expected} match(es), found {num2}");
			}
			foreach (var (num4, constSpec) in list2.OrderByDescending<(int, ConstSpec), int>(((int index, ConstSpec spec) x) => x.index))
			{
				list.InsertRange(num4 + 1, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[3]
				{
					new CodeInstruction(OpCodes.Ldarg_0, (object)null),
					new CodeInstruction(OpCodes.Ldc_I4, (object)constSpec.PassiveId),
					new CodeInstruction(OpCodes.Call, (object)(constSpec.DoubleValue.HasValue ? methodInfo2 : methodInfo))
				});
			}
			return list;
		}

		internal static string ScaledWhat(Ascendancy asc, int id)
		{
			if (asc == null || !Notes.TryGetValue((((object)asc).GetType(), id), out var value))
			{
				return "values";
			}
			return value;
		}

		internal static void LogSummary()
		{
			Plugin.Logger.LogInfo((object)($"Class passive scaling: {Specs.Length - Mismatches}/{Specs.Length} value specs matched" + ((Mismatches > 0) ? " (see warnings above)" : "")));
		}

		static Class_OnOff_Scaling()
		{
			ConstSpec[] obj = new ConstSpec[183]
			{
				I(Barb, "OnTargetAttacked", 1, 100L, "AddMoreDamageOverride"),
				I(Barb, "OnTargetAttacked", 2, 100L, "set_Value"),
				I(Barb, "OnTargetAttacked", 6, 200L, "CheckProc"),
				I(Barb, "OnTargetAttacked", 7, 3L, null, 5L),
				I(Barb, "OnTargetAttacked", 9, 120L, "AddMoreDamageOverride"),
				I(Barb, "OnTargetHit", 3, 30L, "AddStackValue"),
				I(Barb, "OnTargetHit", 18, 50L, "ReduceCooldown", null, null, varMul: false, 0),
				I(Barb, "OnTargetHit", 19, 50L, "ReduceCooldown", null, null, varMul: false, 1),
				I(Barb, "OnSkillCompleted", 10, 1000L),
				D(Barb, "OnSkillCast", 14, 0.2),
				D(Barb, "OnMonsterSlain", 4, 0.1),
				I(Barb, "OnHealthChanged", 11, 1000L, "set_Value"),
				I(Barb, "OnHealthChanged", 17, 200L, "set_Value"),
				I(Temp, "OnEquip", 1, 100L),
				D(Temp, "OnBlock", 4, 0.02, 0),
				D(Temp, "OnBlock", 8, 0.02, 1),
				I(Temp, "OnBlock", 7, 250L, "set_Value"),
				I(Temp, "OnBlock", 7, 100L, "set_Value"),
				I(Temp, "OnBlock", 9, 500L, "ReduceCooldown", null, null, varMul: false, 0),
				I(Temp, "OnBlock", 10, 500L, "ReduceCooldown", null, null, varMul: false, 1),
				I(Temp, "OnBlock", 11, 80L, null, 10000L),
				I(Temp, "OnBlock", 16, 4L, null, 10000L),
				I(Temp, "OnTargetAttacked", 5, 100L, "AddMoreDamageOverride", null, null, varMul: false, 0),
				I(Temp, "OnTargetAttacked", 6, 100L, "AddMoreDamageOverride", null, null, varMul: false, 1),
				D(Temp, "OnTargetAttacked", 14, 0.03),
				D(Temp, "OnTargetAttacked", 18, 0.25),
				D(Temp, "OnThornsAttack", 18, 0.25),
				D(Temp, "OnMaxHealthChanged", 19, 0.02),
				I(Jugg, "OnTickUpdate", 1, 500L, "set_Value"),
				I(Jugg, "OnTickUpdate", 5, 250L, "set_Value"),
				I(Jugg, "OnTickUpdate", 5, 1250L, "set_Value"),
				I(Jugg, "OnTargetAttacked", 2, 100L, "AddMoreDamageOverride"),
				I(Jugg, "OnTargetAttacked", 6, 500L, "AddMoreDamageOverride"),
				I(Jugg, "OnTargetAttacked", 13, 250L, "AddMoreDamageOverride"),
				I(Jugg, "OnTargetAttacked", 18, 150L, "AddMoreDamageOverride"),
				D(Jugg, "OnTargetAttacked", 17, 0.03),
				I(Jugg, "OnDamageTaken", 3, 10L, "set_Value"),
				I(Jugg, "OnDamageTaken", 7, 10L, "AddStackValue"),
				I(Jugg, "OnDamageTaken", 11, 150L, "set_Value"),
				I(Jugg, "OnHealthChanged", 8, -100L, "set_Value"),
				I(Jugg, "OnHealthChanged", 16, 500L, "set_Value"),
				D(Jugg, "OnMaxHealthChanged", 12, 0.01),
				D(Jugg, "OnMaxHealthChanged", 15, 0.03),
				I(Jugg, "OnSkillCompleted", 10, 20L, "CheckProc"),
				I(Jugg, "OnSkillCastFinal", 14, 30L, "CheckProc"),
				I(Ward, "OnBlock", 1, 300L, "set_Value"),
				I(Ward, "OnBlock", 5, 250L, "set_Value", null, null, varMul: false, 0),
				I(Ward, "OnBlock", 5, 1250L, "set_Value"),
				D(Ward, "OnBlock", 3, 0.03, 0),
				D(Ward, "OnBlock", 7, 0.03, 1),
				I(Ward, "OnBlock", 6, 200L),
				I(Ward, "OnBlock", 9, 10L, "AddStackValue"),
				I(Ward, "OnBlock", 11, 100L, "CheckProc", null, null, varMul: false, 0),
				I(Ward, "OnBlock", 15, 100L, "CheckProc", null, null, varMul: false, 1),
				I(Ward, "OnBlock", 12, 250L, "set_Value", null, null, varMul: false, 1),
				I(Ward, "OnBlock", 16, 100L, "set_Value"),
				I(Ward, "OnBlock", 18, 1000L, "ReduceCooldown"),
				I(Ward, "OnTargetHit", 4, 20L, "Min"),
				I(Ward, "OnTargetAttacked", 10, 250L, "AddMoreDamageOverride"),
				I(Ward, "OnTargetAttacked", 13, 100L, "AddMoreDamageOverride"),
				D(Ward, "OnDamageTaken", 20, 0.1),
				I(Assa, "OnTargetAttacked", 1, 100L, "AddMoreDamageOverride"),
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null
			};
			Type assa = Assa;
			long v = 150L;
			OpCode? op = Add;
			obj[62] = I(assa, "OnTargetAttacked", 2, v, null, null, op);
			obj[63] = I(Assa, "OnTargetAttacked", 6, 300L, "AddMoreDamageOverride");
			obj[64] = I(Assa, "OnTargetAttacked", 9, 200L, "CheckProc");
			Type assa2 = Assa;
			long v2 = 100L;
			op = Add;
			obj[65] = I(assa2, "OnTargetAttacked", 18, v2, null, null, op);
			Type assa3 = Assa;
			long v3 = 500L;
			op = Add;
			obj[66] = I(assa3, "OnTargetAttacked", 18, v3, null, null, op);
			Type assa4 = Assa;
			long v4 = 100L;
			op = Add;
			obj[67] = I(assa4, "OnThornsAttack", 18, v4, null, null, op);
			Type assa5 = Assa;
			long v5 = 500L;
			op = Add;
			obj[68] = I(assa5, "OnThornsAttack", 18, v5, null, null, op);
			obj[69] = I(Assa, "OnTargetHit", 3, 30L, "AddStackValue");
			obj[70] = I(Assa, "OnTargetHit", 7, 100L, "set_Value");
			obj[71] = D(Assa, "OnMonsterSlain", 4, 0.1, 0);
			obj[72] = D(Assa, "OnMonsterSlain", 8, 0.1, 1);
			obj[73] = I(Assa, "OnMonsterSlain", 12, -150L, "set_Value");
			obj[74] = I(Assa, "OnMonsterSlain", 16, 100L, "set_Value");
			obj[75] = I(Assa, "OnMonsterSlain", 16, 50L, "set_Value");
			obj[76] = I(Assa, "OnMonsterSlain", 14, 2000L, "ReduceCooldown");
			obj[77] = D(Assa, "OnDodge", 11, 0.05, -1, 2);
			obj[78] = D(Assa, "OnEvade", 11, 0.05, -1, 2);
			obj[79] = I(Assa, "OnDodge", 15, 1000L, "ReduceCooldown");
			obj[80] = I(Assa, "OnEvade", 15, 1000L, "ReduceCooldown");
			obj[81] = I(Assa, "OnSkillCompleted", 19, 500L);
			obj[82] = I(Mark, "OnSkillCast", 1, 15L, null, 0L);
			obj[83] = I(Mark, "OnTargetFirstHit", 5, 5L, null, 0L);
			obj[84] = I(Mark, "OnTargetAttacked", 6, 100L, "AddMoreDamageOverride");
			obj[85] = I(Mark, "ApplyFocusStacks", 2, 5L, null, null, null, varMul: true, 0);
			obj[86] = I(Mark, "ApplyFocusStacks", 10, 5L, null, null, null, varMul: true, 1);
			obj[87] = I(Mark, "ApplyFocusStacks", 12, 15L, null, null, null, varMul: true);
			obj[88] = I(Mark, "ApplyFocusStacks", 20, 2L, null, null, null, varMul: true, -1, 2);
			obj[89] = I(Mark, "LoseFocusStacks", 3, 120L, "set_Value", null, null, varMul: false, 0);
			obj[90] = I(Mark, "LoseFocusStacks", 17, 120L, "set_Value", null, null, varMul: false, 1);
			obj[91] = I(Mark, "LoseFocusStacks", 4, 100L, "set_Value");
			Type mark = Mark;
			long v6 = 50L;
			op = Mul;
			obj[92] = I(mark, "LoseFocusStacks", 14, v6, null, null, op, varMul: false, 0);
			Type mark2 = Mark;
			long v7 = 50L;
			op = Mul;
			obj[93] = I(mark2, "LoseFocusStacks", 16, v7, null, null, op, varMul: false, 1);
			obj[94] = I(Mark, "OnDamageTaken", 8, 5L, null, null, null, varMul: true);
			obj[95] = I(Rene, "OnStaggerChanged", 1, 120L, "set_Value");
			obj[96] = I(Rene, "OnStaggerChanged", 10, 20L, null, null, null, varMul: true, 0);
			obj[97] = I(Rene, "OnStaggerChanged", 19, 20L, null, null, null, varMul: true, 1);
			obj[98] = I(Rene, "ApplySwiftReflexes", 2, 10L, "AddStackValue");
			obj[99] = I(Rene, "ApplySwiftReflexes", 6, 100L, "set_Value");
			obj[100] = I(Rene, "OnEncounterLoopStart", 5, 40L, "set_Value", null, null, varMul: false, -1, 2);
			obj[101] = I(Rene, "OnEncounterLoopStart", 9, 50L, "set_Value");
			obj[102] = I(Rene, "OnDotStacksRemoved", 4, 50L, null, null, null, varMul: true, -1, 2);
			obj[103] = I(Rene, "OnDotStacksRemoved", 12, 100L, "set_Value");
			obj[104] = I(Rene, "OnDotStacksRemoved", 13, 100L, null, null, null, varMul: true, 0);
			obj[105] = I(Rene, "OnDotStacksRemoved", 15, 100L, null, null, null, varMul: true, 1);
			Type rene = Rene;
			long v8 = 5L;
			op = Mul;
			obj[106] = I(rene, "OnHealthChanged", 11, v8, null, null, op);
			obj[107] = I(Rene, "OnTargetAttacked", 14, 100L, "AddMoreDamageOverride");
			obj[108] = I(Rene, "OnTargetAttacked", 17, 200L, "AddMoreDamageOverride");
			obj[109] = I(Arch, "ApplyElementalBlastSuccess", 1, 100L, "set_Value", null, null, varMul: false, 0);
			obj[110] = I(Arch, "ApplyElementalBlastSuccess", 5, 100L, "set_Value", null, null, varMul: false, 1);
			obj[111] = I(Arch, "ApplyElementalBlastSuccess", 20, 100L, "set_Value", null, null, varMul: false, 2);
			obj[112] = D(Arch, "ApplyElementalBlastSuccess", 3, 0.025);
			obj[113] = D(Arch, "ApplyElementalBlastSuccess", 16, 0.05);
			obj[114] = I(Arch, "ApplyElementalBlastSuccess", 14, 150L, "ReduceCooldown", null, null, varMul: false, 0);
			obj[115] = I(Arch, "ApplyElementalBlastSuccess", 15, 150L, "ReduceCooldown", null, null, varMul: false, 1);
			obj[116] = I(Arch, "ApplyElementalBlastTargetHit", 13, -150L, "set_Value");
			obj[117] = I(Arch, "OnTargetAttacked", 7, 100L, "AddMoreDamageOverride");
			obj[118] = I(Arch, "OnChilled", 11, 100L, "set_Value");
			obj[119] = I(Arch, "OnShocked", 12, 100L, "set_Value");
			obj[120] = I(Arch, "OnSkillCompleted", 8, 5L);
			obj[121] = D(Vizi, "ApplyVizierTargetHit", 3, 0.01, 0);
			obj[122] = D(Vizi, "ApplyVizierTargetHit", 7, 0.01, 1);
			obj[123] = I(Vizi, "ApplyVizierTargetHit", 17, 50L, "ReduceCooldown", null, null, varMul: false, 0);
			obj[124] = I(Vizi, "ApplyVizierTargetHit", 20, 50L, "ReduceCooldown", null, null, varMul: false, 1);
			obj[125] = I(Vizi, "OnTargetAttacked", 5, 250L, "AddMoreDamageOverride", null, null, varMul: false, 0);
			obj[126] = I(Vizi, "OnTargetAttacked", 6, 250L, "AddMoreDamageOverride", null, null, varMul: false, 1);
			obj[127] = I(Vizi, "OnTargetAttacked", 13, 1500L, "AddMoreDamageOverride");
			obj[128] = I(Vizi, "OnTargetAttacked", 15, 100L, "AddMoreDamageOverride");
			obj[129] = I(Vizi, "OnTargetAttacked", 18, 120L, "AddMoreDamageOverride");
			obj[130] = I(Vizi, "AddPowerCharges", 9, 200L, "set_Value");
			obj[131] = I(Vizi, "AddPowerCharges", 14, 120L, "set_Value");
			obj[132] = I(Vizi, "AddPowerCharges", 16, 100L, "set_Value");
			obj[133] = I(Vizi, "AddMirrorImageStacks", 12, 100L, "set_Heal");
			obj[134] = I(Batt, "OnBarrierChanged", 1, 100L, "set_Value", null, null, varMul: false, 0);
			obj[135] = I(Batt, "OnBarrierChanged", 9, 100L, "set_Value", null, null, varMul: false, 1);
			obj[136] = I(Batt, "OnBarrierChanged", 17, 100L, "set_Value", null, null, varMul: false, 2);
			obj[137] = I(Batt, "OnBarrierChanged", 7, 400L, "set_Value");
			obj[138] = D(Batt, "OnTargetHit", 4, 0.005, -1, 2);
			obj[139] = I(Batt, "OnTargetHit", 14, 50L, "ReduceCooldown");
			obj[140] = I(Batt, "OnDamageTaken", 5, 500L, "set_Value");
			obj[141] = I(Batt, "OnDamageTaken", 16, 100L, "set_Value");
			obj[142] = I(Batt, "OnTargetAttacked", 13, 100L, "AddMoreDamageOverride");
			obj[143] = D(Batt, "OnTargetAttacked", 18, 0.01);
			obj[144] = D(Batt, "OnMaxBarrierChanged", 19, 0.01, -1, 2);
			obj[145] = D(Batt, "OnRegenTick", 10, 0.1);
			obj[146] = I(Crus, "OnTargetAttacked", 1, 120L, "AddMoreDamageOverride");
			Type crus = Crus;
			long v9 = 30L;
			op = Mul;
			obj[147] = I(crus, "OnTargetAttacked", 7, v9, null, null, op);
			Type crus2 = Crus;
			long v10 = 150L;
			op = Mul;
			obj[148] = I(crus2, "OnTargetAttacked", 7, v10, null, null, op);
			Type crus3 = Crus;
			long v11 = 30L;
			op = Mul;
			obj[149] = I(crus3, "OnThornsAttack", 7, v11, null, null, op);
			Type crus4 = Crus;
			long v12 = 150L;
			op = Mul;
			obj[150] = I(crus4, "OnThornsAttack", 7, v12, null, null, op);
			obj[151] = I(Crus, "OnTargetAttacked", 8, 200L, "CheckProc");
			Type crus5 = Crus;
			long v13 = 150L;
			op = Add;
			obj[152] = I(crus5, "OnTargetAttacked", 11, v13, null, null, op);
			Type crus6 = Crus;
			long v14 = 300L;
			op = Add;
			obj[153] = I(crus6, "UpdateBlessingStrength", 9, v14, null, null, op);
			Type crus7 = Crus;
			long v15 = 50L;
			op = Add;
			obj[154] = I(crus7, "UpdateBlessingStrength", 10, v15, null, null, op, varMul: false, 0);
			Type crus8 = Crus;
			long v16 = 50L;
			op = Add;
			obj[155] = I(crus8, "UpdateBlessingStrength", 12, v16, null, null, op, varMul: false, 1);
			Type crus9 = Crus;
			long v17 = 50L;
			op = Add;
			obj[156] = I(crus9, "UpdateBlessingStrength", 13, v17, null, null, op, varMul: false, 2);
			Type crus10 = Crus;
			long v18 = 50L;
			op = Add;
			obj[157] = I(crus10, "UpdateBlessingStrength", 16, v18, null, null, op, varMul: false, 3);
			obj[158] = I(Crus, "OnSkillCast", 10, 50L, "CheckProc", null, null, varMul: false, 0);
			obj[159] = I(Crus, "OnSkillCast", 12, 50L, "CheckProc", null, null, varMul: false, 1);
			obj[160] = I(Crus, "OnSkillCast", 13, 50L, "CheckProc", null, null, varMul: false, 2);
			obj[161] = I(Crus, "OnSkillCast", 16, 50L, "CheckProc", null, null, varMul: false, 3);
			obj[162] = D(Crus, "OnSkillCast", 3, 0.004, -1, 2);
			obj[163] = D(Crus, "OnSkillCast", 20, 0.02, -1, 2);
			obj[164] = I(Crus, "OnSkillCast", 14, 250L, "ReduceCooldown", null, null, varMul: false, 0);
			obj[165] = I(Crus, "OnSkillCast", 15, 250L, "ReduceCooldown", null, null, varMul: false, 1);
			obj[166] = D(Crus, "OnMaxHealthChanged", 19, 0.03);
			obj[167] = I(Inqu, "OnTargetAttacked", 1, 100L, "AddMoreDamageOverride", null, null, varMul: false, 0);
			obj[168] = I(Inqu, "OnTargetAttacked", 13, 100L, "AddMoreDamageOverride", null, null, varMul: false, 1);
			obj[169] = I(Inqu, "OnTargetAttacked", 6, 200L, "CheckProc");
			Type inqu = Inqu;
			long v19 = 100L;
			op = Add;
			obj[170] = I(inqu, "OnTargetAttacked", 10, v19, null, null, op);
			Type inqu2 = Inqu;
			long v20 = 500L;
			op = Add;
			obj[171] = I(inqu2, "OnTargetAttacked", 10, v20, null, null, op);
			Type inqu3 = Inqu;
			long v21 = 100L;
			op = Add;
			obj[172] = I(inqu3, "OnThornsAttack", 10, v21, null, null, op);
			Type inqu4 = Inqu;
			long v22 = 500L;
			op = Add;
			obj[173] = I(inqu4, "OnThornsAttack", 10, v22, null, null, op);
			obj[174] = I(Inqu, "OnTargetHit", 2, 30L, "AddStackValue");
			obj[175] = D(Inqu, "OnTargetHit", 8, 0.005, -1, 2);
			obj[176] = I(Inqu, "OnTargetHit", 15, 50L, "ReduceCooldown", null, null, varMul: false, 0);
			obj[177] = I(Inqu, "OnTargetHit", 16, 50L, "ReduceCooldown", null, null, varMul: false, 1);
			obj[178] = D(Inqu, "OnMonsterSlain", 4, 0.1, -1, 2);
			obj[179] = I(Inqu, "OnBarrierChanged", 11, 100L);
			obj[180] = I(Inqu, "OnSkillCast", 14, 100L, "CheckProc");
			obj[181] = I(Inqu, "OnSkillCast", 14, 80L, null, 5000L);
			obj[182] = D(Inqu, "UpdateProtectiveInvocation", 19, 0.005, -1, 2);
			Specs = obj;
			Notes = new Dictionary<(Type, int), string>
			{
				{
					(typeof(Barbarian), 3),
					"max stacks"
				},
				{
					(typeof(Assassin), 3),
					"max stacks"
				},
				{
					(typeof(Inquisitor), 2),
					"max stacks"
				},
				{
					(typeof(Juggernaut), 7),
					"max stacks"
				},
				{
					(typeof(Warden), 4),
					"max stacks"
				},
				{
					(typeof(Warden), 9),
					"max stacks"
				},
				{
					(typeof(Renegade), 2),
					"max stacks"
				},
				{
					(typeof(Archmage), 8),
					"number of targets"
				},
				{
					(typeof(Marksman), 1),
					"focus stacks gained"
				},
				{
					(typeof(Marksman), 5),
					"focus stacks gained"
				}
			};
		}
	}
	[HarmonyPatch(typeof(MasterySkill), "SetupExperience")]
	internal static class Mastery_SetupExperience
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> ins)
		{
			return Util.SwapConst(ins, "MasterySkill.SetupExperience", 30, Plugin.MaxMasteryLevel.Value, 1);
		}

		private static void Postfix(MasterySkill __instance)
		{
			int baseMasteryLevel = __instance.BaseMasteryLevel;
			if (baseMasteryLevel >= 30)
			{
				int value = Plugin.MaxMasteryLevel.Value;
				int num = Math.Min(baseMasteryLevel, value - 1);
				double num2 = (double)__instance.MaxExperience * (1.0 + (double)(Math.Max(0f, Plugin.MasteryXpGrowthPerLevel.Value) * (float)(num - 29)));
				__instance.MaxExperience = ((num2 >= 2147483646.0) ? 2147483646 : Math.Max(1, (int)num2));
				if (baseMasteryLevel >= value)
				{
					__instance.CurrentExperience = __instance.MaxExperience;
				}
			}
		}
	}
	[HarmonyPatch(typeof(MasterySkill), "AddMasteryExperience")]
	internal static class Mastery_AddMasteryExperience
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> ins)
		{
			return Util.SwapConst(ins, "MasterySkill.AddMasteryExperience", 30, Plugin.MaxMasteryLevel.Value, 2);
		}
	}
	[HarmonyPatch(typeof(MasteryPassivePanelController), "UpdateSkillInfoPanel")]
	internal static class Mastery_InfoPanel
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> ins)
		{
			return Util.SwapConst(ins, "MasteryPassivePanelController.UpdateSkillInfoPanel", 30, Plugin.MaxMasteryLevel.Value, 1);
		}
	}
	[HarmonyPatch(typeof(SaveFile), "LoadMasterySkill")]
	internal static class Mastery_LoadMasterySkill
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> ins)
		{
			return Util.SwapConst(ins, "SaveFile.LoadMasterySkill", 30, Plugin.MaxMasteryLevel.Value, 1);
		}
	}
	[HarmonyPatch(typeof(SaveFile), "LoadFactionCooldown")]
	internal static class Mastery_LoadFactionCooldown
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> ins)
		{
			return Util.SwapConst(ins, "SaveFile.LoadFactionCooldown", 30, Plugin.MaxMasteryLevel.Value, 1);
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class AscendancyPassive_Tooltip
	{
		private static string Pct(int rank)
		{
			return $"{Math.Round(ClassScaling.Mult(rank) * 100.0)}%";
		}

		private static void Postfix(AscendancyPassive __instance, ref string __result)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrEmpty(__result) && ((Passive)__instance).MaxRank > 1)
			{
				Ascendancy value = Traverse.Create((object)__instance).Property("Ascendancy", (object[])null).GetValue<Ascendancy>();
				if (value != null && Ranks.IsScalingClassPassive(value.Class, ((Passive)__instance).ID))
				{
					int currentRank = ((Passive)__instance).CurrentRank;
					int maxRank = ((Passive)__instance).MaxRank;
					string text = Class_OnOff_Scaling.ScaledWhat(value, ((Passive)__instance).ID);
					string text2 = ((currentRank <= 0) ? $"Scales with rank: up to {Pct(maxRank)} of listed {text} at rank {maxRank}" : ((currentRank < maxRank) ? ("Current effect: " + Pct(currentRank) + " of listed " + text + " (next rank: " + Pct(currentRank + 1) + ")") : ("Current effect: " + Pct(currentRank) + " of listed " + text + " (max rank)")));
					string text3 = "\n" + TextHelper.GetHtmlText(text2, "#95FF6D", false, -1);
					string htmlText = TextHelper.GetHtmlText(((Passive)__instance).Description, "#518AD6", false, -1);
					int num = __result.IndexOf(htmlText, StringComparison.Ordinal);
					__result = ((num >= 0) ? __result.Insert(num + htmlText.Length, text3) : (__result + text3));
				}
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "nemonline.lootun.beyond150";

		public const string PLUGIN_NAME = "Beyond 150";

		public const string PLUGIN_VERSION = "1.0.2";
	}
}