Decompiled source of R2API RecalculateStats v1.4.0

plugins/R2API.RecalculateStats/R2API.RecalculateStats.dll

Decompiled 3 months ago
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using IL.RoR2;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using R2API.AutoVersionGen;
using R2API.Utils;
using RoR2;
using UnityEngine;

[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("R2API.RecalculateStats")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0+137f3a56b0ab9ad9ca0bebf706ce6015764f2645")]
[assembly: AssemblyProduct("R2API.RecalculateStats")]
[assembly: AssemblyTitle("R2API.RecalculateStats")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	[DebuggerNonUserCode]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	[DebuggerNonUserCode]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
}
namespace R2API
{
	[AutoVersion]
	public static class RecalculateStatsAPI
	{
		public class StatHookEventArgs : EventArgs
		{
			[EditorBrowsable(EditorBrowsableState.Never)]
			public const string _levelMultiplier = "Used for internal documentation";

			public float baseHealthAdd;

			public float levelHealthAdd;

			public float healthMultAdd;

			public float baseShieldAdd;

			public float levelShieldAdd;

			public float shieldMultAdd;

			public float baseRegenAdd;

			public float levelRegenAdd;

			public float regenMultAdd;

			public float baseMoveSpeedAdd;

			public float levelMoveSpeedAdd;

			public float moveSpeedMultAdd;

			public float moveSpeedReductionMultAdd;

			public float sprintSpeedAdd;

			public int moveSpeedRootCount;

			public float baseJumpPowerAdd;

			public float levelJumpPowerAdd;

			public float jumpPowerMultAdd;

			public float baseDamageAdd;

			public float levelDamageAdd;

			public float damageMultAdd;

			public float baseAttackSpeedAdd;

			public float levelAttackSpeedAdd;

			public float attackSpeedMultAdd;

			public float attackSpeedReductionMultAdd;

			public float critAdd;

			public float levelCritAdd;

			public float critDamageMultAdd;

			public float armorAdd;

			public float levelArmorAdd;

			public float baseCurseAdd;

			public float cooldownReductionAdd;

			public float cooldownMultAdd;

			public float primaryCooldownMultAdd;

			public float secondaryCooldownMultAdd;

			public float utilityCooldownMultAdd;

			public float specialCooldownMultAdd;

			public float levelFlatAdd;

			public float levelMultAdd;
		}

		public delegate void StatHookEventHandler(CharacterBody sender, StatHookEventArgs args);

		[CompilerGenerated]
		private static class <>O
		{
			public static Manipulator <0>__HookRecalculateStats;

			public static Action<CharacterBody> <1>__GetStatMods;
		}

		public const string PluginGUID = "com.bepis.r2api.recalculatestats";

		public const string PluginName = "R2API.RecalculateStats";

		private static bool _hooksEnabled;

		private static StatHookEventArgs StatMods;

		public const string PluginVersion = "1.4.0";

		[Obsolete("All submodules are automatically loaded and this property is now unused")]
		public static bool Loaded => true;

		private static event StatHookEventHandler _getStatCoefficients;

		public static event StatHookEventHandler GetStatCoefficients
		{
			add
			{
				SetHooks();
				_getStatCoefficients += value;
			}
			remove
			{
				_getStatCoefficients -= value;
				if (RecalculateStatsAPI._getStatCoefficients != null)
				{
					Delegate[] invocationList = RecalculateStatsAPI._getStatCoefficients.GetInvocationList();
					if (invocationList == null || invocationList.Length != 0)
					{
						return;
					}
				}
				UnsetHooks();
			}
		}

		internal static void SetHooks()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			if (!_hooksEnabled)
			{
				object obj = <>O.<0>__HookRecalculateStats;
				if (obj == null)
				{
					Manipulator val = HookRecalculateStats;
					<>O.<0>__HookRecalculateStats = val;
					obj = (object)val;
				}
				CharacterBody.RecalculateStats += (Manipulator)obj;
				_hooksEnabled = true;
			}
		}

		internal static void UnsetHooks()
		{
			//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_001b: Expected O, but got Unknown
			object obj = <>O.<0>__HookRecalculateStats;
			if (obj == null)
			{
				Manipulator val = HookRecalculateStats;
				<>O.<0>__HookRecalculateStats = val;
				obj = (object)val;
			}
			CharacterBody.RecalculateStats -= (Manipulator)obj;
			_hooksEnabled = false;
		}

		private static void HookRecalculateStats(ILContext il)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			ILCursor c = new ILCursor(il);
			c.Emit(OpCodes.Ldarg_0);
			c.EmitDelegate<Action<CharacterBody>>((Action<CharacterBody>)GetStatMods);
			FindLocLevelMultiplierIndex(c, out var locLevelMultiplierIndex);
			Action emitLevelMultiplier = ((locLevelMultiplierIndex >= 0) ? new Action(EmitLevelMultiplier) : new Action(EmitFallbackLevelMultiplier));
			ModifyHealthStat(c, emitLevelMultiplier);
			ModifyShieldStat(c, emitLevelMultiplier);
			ModifyHealthRegenStat(c, emitLevelMultiplier);
			ModifyMovementSpeedStat(c, emitLevelMultiplier);
			ModifyJumpStat(c, emitLevelMultiplier);
			ModifyDamageStat(c, emitLevelMultiplier);
			ModifyAttackSpeedStat(c, emitLevelMultiplier);
			ModifyCritStat(c, emitLevelMultiplier);
			ModifyArmorStat(c, emitLevelMultiplier);
			ModifyCurseStat(c);
			ModifyCooldownStat(c);
			ModifyLevelingStat(c);
			void EmitFallbackLevelMultiplier()
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				c.Emit(OpCodes.Ldc_R4, 0f);
			}
			void EmitLevelMultiplier()
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				c.Emit(OpCodes.Ldloc, locLevelMultiplierIndex);
			}
		}

		private static void GetStatMods(CharacterBody characterBody)
		{
			StatMods = new StatHookEventArgs();
			if (RecalculateStatsAPI._getStatCoefficients == null)
			{
				return;
			}
			Delegate[] invocationList = RecalculateStatsAPI._getStatCoefficients.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				StatHookEventHandler statHookEventHandler = (StatHookEventHandler)invocationList[i];
				try
				{
					statHookEventHandler(characterBody, StatMods);
				}
				catch (Exception arg)
				{
					RecalculateStatsPlugin.Logger.LogError((object)$"Exception thrown by : {statHookEventHandler.Method.DeclaringType.Name}.{statHookEventHandler.Method.Name}:\n{arg}");
				}
			}
		}

		private static void FindLocLevelMultiplierIndex(ILCursor c, out int locLevelMultiplierIndex)
		{
			c.Index = 0;
			int _locLevelMultiplierIndex = -1;
			c.TryGotoNext(new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertyGetter(typeof(CharacterBody), "level")),
				(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 1f),
				(Instruction x) => ILPatternMatchingExt.MatchSub(x),
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref _locLevelMultiplierIndex)
			});
			locLevelMultiplierIndex = _locLevelMultiplierIndex;
			if (locLevelMultiplierIndex < 0)
			{
				RecalculateStatsPlugin.Logger.LogError((object)"FindLocLevelMultiplierIndex failed! Level-scaled stats will be ignored!");
			}
		}

		private static void ModifyCurseStat(ILCursor c)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			c.Index = 0;
			if (c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[3]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 10f),
				(Instruction x) => ILPatternMatchingExt.MatchMul(x),
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "cursePenalty"))
			}))
			{
				c.MoveAfterLabels();
				c.Emit(OpCodes.Ldarg_0);
				c.EmitDelegate<Action<CharacterBody>>((Action<CharacterBody>)delegate(CharacterBody body)
				{
					body.cursePenalty += StatMods.baseCurseAdd;
				});
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyCurseStat failed.");
			}
		}

		private static void ModifyCooldownStat(ILCursor c)
		{
			c.Index = 0;
			int num = 0;
			while (c.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "cooldownScale"))
			}) && c.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "flatCooldownReduction"))
			}))
			{
				num++;
			}
			if (num >= 4)
			{
				c.Index = 0;
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "cooldownScale"))
				});
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown * (1f + StatMods.cooldownMultAdd + StatMods.primaryCooldownMultAdd)));
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "flatCooldownReduction"))
				});
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown + StatMods.cooldownReductionAdd));
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "cooldownScale"))
				});
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown * (1f + StatMods.cooldownMultAdd + StatMods.secondaryCooldownMultAdd)));
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "flatCooldownReduction"))
				});
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown + StatMods.cooldownReductionAdd));
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "cooldownScale"))
				});
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown * (1f + StatMods.cooldownMultAdd + StatMods.utilityCooldownMultAdd)));
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "flatCooldownReduction"))
				});
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown + StatMods.cooldownReductionAdd));
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "cooldownScale"))
				});
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown * (1f + StatMods.cooldownMultAdd + StatMods.specialCooldownMultAdd)));
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(GenericSkill), "flatCooldownReduction"))
				});
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldCooldown) => oldCooldown + StatMods.cooldownReductionAdd));
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyCooldownStat failed.");
			}
		}

		private static void ModifyLevelingStat(ILCursor c)
		{
			c.Index = 0;
			if (c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[3]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertyGetter(typeof(CharacterBody), "level")),
				(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 1f),
				(Instruction x) => ILPatternMatchingExt.MatchSub(x)
			}))
			{
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float oldScaling) => (oldScaling + StatMods.levelFlatAdd) * (1f + StatMods.levelMultAdd)));
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyLevelingStat failed.");
			}
		}

		private static void ModifyArmorStat(ILCursor c, Action emitLevelMultiplier)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			c.Index = 0;
			if (c.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseArmor")
			}) && c.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "armor"))
			}))
			{
				emitLevelMultiplier();
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.armorAdd + StatMods.levelArmorAdd * levelMultiplier));
				c.Emit(OpCodes.Add);
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyArmorStat failed.");
			}
		}

		private static void ModifyAttackSpeedStat(ILCursor c, Action emitLevelMultiplier)
		{
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			c.Index = 0;
			int locBaseAttackSpeedIndex = -1;
			int locAttackSpeedMultIndex = -1;
			if (c.TryGotoNext(new Func<Instruction, bool>[3]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseAttackSpeed"),
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelAttackSpeed")
			}) && c.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseAttackSpeedIndex)
			}) && c.TryGotoNext(new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, locBaseAttackSpeedIndex),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locAttackSpeedMultIndex),
				(Instruction x) => ILPatternMatchingExt.MatchMul(x),
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseAttackSpeedIndex)
			}))
			{
				c.GotoPrev(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseAttackSpeed")
				});
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseAttackSpeedIndex)
				});
				emitLevelMultiplier();
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseAttackSpeedAdd + StatMods.levelAttackSpeedAdd * levelMultiplier));
				c.Emit(OpCodes.Add);
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locAttackSpeedMultIndex)
				});
				c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.attackSpeedMultAdd));
				c.Emit(OpCodes.Add);
				c.GotoNext(new Func<Instruction, bool>[2]
				{
					(Instruction x) => ILPatternMatchingExt.MatchDiv(x),
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locAttackSpeedMultIndex)
				});
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float origSpeedReductionMult) => Mathf.Max(Mathf.Epsilon, origSpeedReductionMult + StatMods.attackSpeedReductionMultAdd)));
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyAttackSpeedStat failed.");
			}
		}

		private static void ModifyCritStat(ILCursor c, Action emitLevelMultiplier)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			c.Index = 0;
			int locOrigCrit = -1;
			if (c.TryGotoNext(new Func<Instruction, bool>[3]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locOrigCrit),
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "crit"))
			}) && c.TryGotoPrev((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "critMultiplier"))
			}))
			{
				int index = c.Index;
				c.Index = index - 1;
				c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.critDamageMultAdd));
				c.Emit(OpCodes.Add);
				c.GotoNext((MoveType)2, new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locOrigCrit)
				});
				c.Emit(OpCodes.Ldloc, locOrigCrit);
				emitLevelMultiplier();
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.critAdd + StatMods.levelCritAdd * levelMultiplier));
				c.Emit(OpCodes.Add);
				c.Emit(OpCodes.Stloc, locOrigCrit);
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyCritStat failed.");
			}
		}

		private static void ModifyDamageStat(ILCursor c, Action emitLevelMultiplier)
		{
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			c.Index = 0;
			int locBaseDamageIndex = -1;
			int locDamageMultIndex = -1;
			if (c.TryGotoNext(new Func<Instruction, bool>[3]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseDamage"),
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelDamage")
			}) && c.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseDamageIndex)
			}) && c.TryGotoNext(new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, locBaseDamageIndex),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locDamageMultIndex),
				(Instruction x) => ILPatternMatchingExt.MatchMul(x),
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseDamageIndex)
			}))
			{
				c.GotoPrev(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseDamage")
				});
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseDamageIndex)
				});
				emitLevelMultiplier();
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseDamageAdd + StatMods.levelDamageAdd * levelMultiplier));
				c.Emit(OpCodes.Add);
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locDamageMultIndex)
				});
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float origDamageMult) => origDamageMult + StatMods.damageMultAdd));
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyDamageStat failed.");
			}
		}

		private static void ModifyJumpStat(ILCursor c, Action emitLevelMultiplier)
		{
			c.Index = 0;
			int num = default(int);
			if (c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[6]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseJumpPower"),
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelJumpPower"),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num),
				(Instruction x) => ILPatternMatchingExt.MatchMul(x),
				(Instruction x) => ILPatternMatchingExt.MatchAdd(x)
			}))
			{
				emitLevelMultiplier();
				c.EmitDelegate<Func<float, float, float>>((Func<float, float, float>)((float origJumpPower, float levelMultiplier) => (origJumpPower + StatMods.baseJumpPowerAdd + StatMods.levelJumpPowerAdd * levelMultiplier) * (1f + StatMods.jumpPowerMultAdd)));
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyJumpStat failed.");
			}
		}

		private static void ModifyHealthStat(ILCursor c, Action emitLevelMultiplier)
		{
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			c.Index = 0;
			int locBaseHealthIndex = -1;
			int locHealthMultIndex = -1;
			if (c.TryGotoNext(new Func<Instruction, bool>[3]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseMaxHealth"),
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelMaxHealth")
			}) && c.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseHealthIndex)
			}) && c.TryGotoNext(new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, locBaseHealthIndex),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locHealthMultIndex),
				(Instruction x) => ILPatternMatchingExt.MatchMul(x),
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseHealthIndex)
			}))
			{
				c.GotoPrev(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseMaxHealth")
				});
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseHealthIndex)
				});
				emitLevelMultiplier();
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseHealthAdd + StatMods.levelHealthAdd * levelMultiplier));
				c.Emit(OpCodes.Add);
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locHealthMultIndex)
				});
				c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.healthMultAdd));
				c.Emit(OpCodes.Add);
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyHealthStat failed.");
			}
		}

		private static void ModifyShieldStat(ILCursor c, Action emitLevelMultiplier)
		{
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			c.Index = 0;
			int locBaseShieldIndex = -1;
			if (c.TryGotoNext(new Func<Instruction, bool>[3]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseMaxShield"),
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelMaxShield")
			}) && c.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseShieldIndex)
			}) && c.TryGotoNext(new Func<Instruction, bool>[2]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, locBaseShieldIndex),
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "maxShield"))
			}))
			{
				int index = c.Index;
				c.Index = index + 1;
				c.EmitDelegate<Func<float>>((Func<float>)(() => 1f + StatMods.shieldMultAdd));
				c.Emit(OpCodes.Mul);
				c.GotoPrev(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelMaxShield")
				});
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseShieldIndex)
				});
				emitLevelMultiplier();
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseShieldAdd + StatMods.levelShieldAdd * levelMultiplier));
				c.Emit(OpCodes.Add);
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyShieldStat failed.");
			}
		}

		private static void ModifyHealthRegenStat(ILCursor c, Action emitLevelMultiplier)
		{
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			c.Index = 0;
			int locRegenMultIndex = -1;
			int locFinalRegenIndex = -1;
			if (c.TryGotoNext(new Func<Instruction, bool>[2]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locFinalRegenIndex),
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertySetter(typeof(CharacterBody), "regen"))
			}) && c.TryGotoPrev(new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchAdd(x),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locRegenMultIndex),
				(Instruction x) => ILPatternMatchingExt.MatchMul(x),
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locFinalRegenIndex)
			}))
			{
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locRegenMultIndex)
				});
				emitLevelMultiplier();
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseRegenAdd + StatMods.levelRegenAdd * levelMultiplier));
				c.Emit(OpCodes.Add);
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchMul(x)
				});
				c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.regenMultAdd));
				c.Emit(OpCodes.Add);
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyHealthRegenStat failed.");
			}
		}

		private static void ModifyMovementSpeedStat(ILCursor c, Action emitLevelMultiplier)
		{
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			c.Index = 0;
			int locBaseSpeedIndex = -1;
			int locSpeedMultIndex = -1;
			int locSpeedDivIndex = -1;
			int num2 = default(int);
			int num = default(int);
			if (c.TryGotoNext(new Func<Instruction, bool>[3]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseMoveSpeed"),
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelMoveSpeed")
			}) && c.TryGotoNext(new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref locBaseSpeedIndex)
			}) && c.TryGotoNext(new Func<Instruction, bool>[6]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, locBaseSpeedIndex),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locSpeedMultIndex),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref locSpeedDivIndex),
				(Instruction x) => ILPatternMatchingExt.MatchDiv(x),
				(Instruction x) => ILPatternMatchingExt.MatchMul(x),
				(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseSpeedIndex)
			}) && c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num2),
				(Instruction x) => ILPatternMatchingExt.MatchOr(x),
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num),
				(Instruction x) => ILPatternMatchingExt.MatchOr(x)
			}))
			{
				c.EmitDelegate<Func<bool>>((Func<bool>)(() => StatMods.moveSpeedRootCount > 0));
				c.Emit(OpCodes.Or);
				c.GotoPrev(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelMoveSpeed")
				});
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locBaseSpeedIndex)
				});
				emitLevelMultiplier();
				c.EmitDelegate<Func<float, float>>((Func<float, float>)((float levelMultiplier) => StatMods.baseMoveSpeedAdd + StatMods.levelMoveSpeedAdd * levelMultiplier));
				c.Emit(OpCodes.Add);
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locSpeedMultIndex)
				});
				c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.moveSpeedMultAdd));
				c.Emit(OpCodes.Add);
				while (c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "sprintingSpeedMultiplier")
				}))
				{
					c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.sprintSpeedAdd));
					c.Emit(OpCodes.Add);
				}
				c.GotoPrev((MoveType)2, new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)Reflection.GetPropertyGetter(typeof(CharacterBody), "isSprinting"))
				});
				c.Emit(OpCodes.Ldarg_0);
				c.EmitDelegate<Func<bool, CharacterBody, bool>>((Func<bool, CharacterBody, bool>)((bool isSprinting, CharacterBody sender) => isSprinting && sender.sprintingSpeedMultiplier + StatMods.sprintSpeedAdd != 0f));
				c.GotoNext(new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchStloc(x, locSpeedDivIndex)
				});
				c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.moveSpeedReductionMultAdd));
				c.Emit(OpCodes.Add);
			}
			else
			{
				RecalculateStatsPlugin.Logger.LogError((object)"ModifyMovementSpeedStat failed.");
			}
		}
	}
	[BepInPlugin("com.bepis.r2api.recalculatestats", "R2API.RecalculateStats", "1.4.0")]
	public sealed class RecalculateStatsPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger { get; set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
		}

		private void OnDestroy()
		{
			RecalculateStatsAPI.UnsetHooks();
		}
	}
	public static class StandardLevelScaling
	{
		public const float Health = 0.3f;

		public const float Shield = 0.3f;

		public const float Regen = 0.2f;

		public const float Damage = 0.2f;
	}
}
namespace R2API.AutoVersionGen
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	internal class AutoVersionAttribute : Attribute
	{
	}
}