Decompiled source of MoreStats v1.4.0

MoreStats.dll

Decompiled 4 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using EntityStates;
using IL.EntityStates;
using IL.RoR2;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using On.EntityStates;
using On.RoR2;
using RoR2;
using RoR2BepInExPack.Utilities;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("MoreStats")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MoreStats")]
[assembly: AssemblyTitle("MoreStats")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: UnverifiableCode]
namespace MoreStats;

public static class BaseStats
{
	public static bool ApplyShieldConversionHook = false;

	public static float PerfectedHealthBonus = 0.25f;

	public static float TranscendenceHealthBonusBase = 0.5f;

	public static float TranscendenceHealthBonusStack = 0.25f;

	public static float TranscendenceShieldConversionFractionBase = 1f;

	public static float TranscendenceShieldConversionFractionStack = 0f;

	public static float PerfectedShieldConversionFraction = 1f;

	public static float OverloadingShieldConversionFraction = 0.5f;

	public static float BaseShieldDelaySeconds = 7f;

	public static float MinShieldDelaySeconds = 1f;

	public static float BarrierLowDecayFactor = 0.5f;

	public static float BarrierHighDecayFactor = 3f;

	public static float BarrierDecayStaticMaxHealthTime = 30f;

	public static int FeatherJumpCountBase = 1;

	public static int FeatherJumpCountStack = 1;

	public static bool IncludeStrangeScrapInScrapTotal = true;
}
[BepInPlugin("com.RiskOfBrainrot.MoreStats", "MoreStats", "1.3.0")]
public class MoreStatsPlugin : BaseUnityPlugin
{
	public const string guid = "com.RiskOfBrainrot.MoreStats";

	public const string teamName = "RiskOfBrainrot";

	public const string modName = "MoreStats";

	public const string version = "1.3.0";

	public static PluginInfo PInfo { get; private set; }

	private void Awake()
	{
		StatHooks.Init();
		OnHit.Init();
		JumpAPI.Init();
	}

	public static void DebugBreakpoint(string methodName, int breakpointNumber = -1)
	{
		string text = "MoreStats: " + methodName + " IL hook failed!";
		if (breakpointNumber >= 0)
		{
			text += $" (breakpoint {breakpointNumber})";
		}
		Debug.LogError((object)text);
	}
}
public static class OnHit
{
	public delegate void HitHookEventHandler(CharacterBody attackerBody, DamageInfo damageInfo, CharacterBody victimBody);

	private static bool initialized;

	public static event HitHookEventHandler GetHitBehavior;

	internal static void Init()
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		if (!initialized)
		{
			initialized = true;
			GlobalEventManager.ProcessHitEnemy += new hook_ProcessHitEnemy(GlobalEventManager_OnHitEnemy);
		}
	}

	private static void GlobalEventManager_OnHitEnemy(orig_ProcessHitEnemy orig, GlobalEventManager self, DamageInfo damageInfo, GameObject victim)
	{
		if (Object.op_Implicit((Object)(object)damageInfo.attacker) && damageInfo.procCoefficient > 0f)
		{
			CharacterBody val = null;
			CharacterBody victimBody = null;
			if (damageInfo.attacker.TryGetComponent<CharacterBody>(ref val) && victim.TryGetComponent<CharacterBody>(ref victimBody))
			{
				CharacterMaster master = val.master;
				if ((Object)(object)master != (Object)null)
				{
					DoIgniteOnHit(damageInfo, victim, val, victimBody);
					OnHit.GetHitBehavior?.Invoke(val, damageInfo, victimBody);
				}
			}
		}
		orig.Invoke(self, damageInfo, victim);
	}

	private static void DoIgniteOnHit(DamageInfo damageInfo, GameObject victim, CharacterBody attackerBody, CharacterBody victimBody)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		Inventory inventory = attackerBody.inventory;
		if (!((Enum)damageInfo.damageType.damageType).HasFlag((Enum)(object)(DamageType)128))
		{
			float burnChance = StatHooks.GetMoreStatsFromBody(attackerBody).burnChance;
			if (burnChance > 0f)
			{
				ref DamageType damageType = ref damageInfo.damageType.damageType;
				damageType = (DamageType)((uint)damageType | 0x80u);
			}
		}
	}
}
public static class JumpAPI
{
	public class JumpSynergyInfo
	{
		public bool isConditionalJump = false;

		public bool didJumpIgnoreRequirements = false;

		public bool isAirJump = false;

		public JumpSynergyInfo(bool isConditionalJump, bool didJumpIgnoreRequirements)
		{
			this.isConditionalJump = isConditionalJump;
			this.didJumpIgnoreRequirements = didJumpIgnoreRequirements;
		}
	}

	public delegate bool ConditionalJumpHandler(CharacterMotor sender, bool jumpIgnoredRequirements);

	public delegate void OnJumpSynergyHandler(CharacterMotor sender, JumpSynergyInfo jumpSynergyInfo);

	private static bool initialized;

	private static float verticalBonus;

	private static float horizontalBonus;

	private static bool didConditionalJump;

	private static bool jumpInputReceived;

	private static bool ignoredRequirements;

	public static event ConditionalJumpHandler OnConditionalJumpUrgent;

	public static event ConditionalJumpHandler OnConditionalJumpPriority;

	public static event ConditionalJumpHandler OnConditionalJumpLast;

	public static event OnJumpSynergyHandler OnJumpEvent;

	public static bool IsDoubleJump(CharacterMotor motor)
	{
		CharacterBody body = motor.body;
		int maxJumpCount = body.maxJumpCount;
		int baseJumpCount = body.baseJumpCount;
		int jumpCount = motor.jumpCount;
		if (jumpCount >= baseJumpCount)
		{
			return true;
		}
		return false;
	}

	public static bool IsBaseJump(CharacterMotor motor, bool mustBeGrounded = false)
	{
		CharacterBody body = motor.body;
		int maxJumpCount = body.maxJumpCount;
		int baseJumpCount = body.baseJumpCount;
		int jumpCount = motor.jumpCount;
		if (mustBeGrounded)
		{
			return jumpCount == 0;
		}
		if (jumpCount < baseJumpCount)
		{
			return true;
		}
		return false;
	}

	public static bool IsLastJump(CharacterMotor motor)
	{
		CharacterBody body = motor.body;
		int maxJumpCount = body.maxJumpCount;
		int baseJumpCount = body.baseJumpCount;
		int jumpCount = motor.jumpCount;
		if (jumpCount >= maxJumpCount - 1)
		{
			return true;
		}
		return false;
	}

	public static void ProposeJumpPowerBonusForCurrentJump(float vBonus = 0f, float hBonus = 0f)
	{
		if (verticalBonus <= vBonus)
		{
			verticalBonus = vBonus;
		}
		if (horizontalBonus <= hBonus)
		{
			horizontalBonus = hBonus;
		}
	}

	internal static void Init()
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		if (!initialized)
		{
			initialized = true;
			GenericCharacterMain.ProcessJump_bool += new Manipulator(InsertConditionalJumps);
		}
	}

	private static void InsertConditionalJump(orig_ProcessJump_bool orig, GenericCharacterMain self, bool ignoreRequirements)
	{
		orig.Invoke(self, ignoreRequirements);
	}

	private static void InsertConditionalJumps(ILContext il)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		ILCursor val = new ILCursor(il);
		val.Index = 0;
		InsertConditionalJumpProc(val);
		val.Index = 0;
		InsertJumpBonus(val);
	}

	private static void InsertJumpBonus(ILCursor c)
	{
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		int num = default(int);
		if (!c.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<GenericCharacterMain>(x, "ApplyJumpVelocity")
		}) || !c.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[2]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num),
			(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num)
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("InsertJumpBonus", 0);
			return;
		}
		int index = c.Index;
		c.Index = index + 1;
		c.EmitDelegate<Func<float, float>>((Func<float, float>)((float hBonusIn) => AddJumpBonus(hBonusIn, horizontalBonus)));
		index = c.Index;
		c.Index = index + 1;
		c.EmitDelegate<Func<float, float>>((Func<float, float>)((float vBonusIn) => AddJumpBonus(vBonusIn, verticalBonus)));
		c.GotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<GenericCharacterMain>(x, "ApplyJumpVelocity")
		});
		c.Emit(OpCodes.Ldarg_0);
		c.EmitDelegate<Action<GenericCharacterMain>>((Action<GenericCharacterMain>)delegate(GenericCharacterMain self)
		{
			JumpAPI.OnJumpEvent?.Invoke(((EntityState)self).characterMotor, new JumpSynergyInfo(didConditionalJump, ignoredRequirements));
		});
		static float AddJumpBonus(float bonusIn, float bonusBonus)
		{
			return bonusIn + bonusBonus;
		}
	}

	private static void InsertConditionalJumpProc(ILCursor c)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		c.Emit(OpCodes.Ldarg_0);
		c.Emit(OpCodes.Ldarg_1);
		c.EmitDelegate<Action<GenericCharacterMain, bool>>((Action<GenericCharacterMain, bool>)delegate(GenericCharacterMain self, bool ignoreRequirements)
		{
			verticalBonus = 0f;
			horizontalBonus = 0f;
			didConditionalJump = false;
			jumpInputReceived = self.jumpInputReceived;
			ignoredRequirements = ignoreRequirements;
			if (jumpInputReceived && ((BaseCharacterMain)self).hasCharacterMotor && ((EntityState)self).characterMotor.jumpCount > 0 && NetworkServer.active && GetConditionalJump(self, ignoreRequirements))
			{
				didConditionalJump = true;
			}
		});
		int num = default(int);
		if (!c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdfld<GenericCharacterMain>(x, "jumpInputReceived")
		}) || !c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num)
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("InsertConditionalJumpProc", 1);
			return;
		}
		c.Emit(OpCodes.Ldarg_0);
		c.EmitDelegate<Func<bool, GenericCharacterMain, bool>>((Func<bool, GenericCharacterMain, bool>)((bool canJump, GenericCharacterMain characterMain) => (jumpInputReceived && (canJump || didConditionalJump)) ? true : false));
		if (!c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[2]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterMotor>(x, "jumpCount"),
			(Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 1)
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("InsertConditionalJumpProc", 2);
			return;
		}
		c.EmitDelegate<Func<int, int>>((Func<int, int>)((int jumpCountToAdd) => (!didConditionalJump) ? jumpCountToAdd : 0));
	}

	private static bool GetConditionalJump(GenericCharacterMain self, bool jumpIgnoredRequirements)
	{
		if (InvokeJumpSequentially(JumpAPI.OnConditionalJumpUrgent, onlyOneJump: false))
		{
			return true;
		}
		if (((EntityState)self).characterMotor.jumpCount < ((EntityState)self).characterBody.baseJumpCount)
		{
			return false;
		}
		if (InvokeJumpSequentially(JumpAPI.OnConditionalJumpPriority, onlyOneJump: true))
		{
			return true;
		}
		if (((EntityState)self).characterMotor.jumpCount < ((EntityState)self).characterBody.maxJumpCount)
		{
			return false;
		}
		if (InvokeJumpSequentially(JumpAPI.OnConditionalJumpLast, onlyOneJump: true))
		{
			return true;
		}
		return false;
		bool InvokeJumpSequentially(ConditionalJumpHandler jumpEvent, bool onlyOneJump)
		{
			if (jumpEvent == null)
			{
				return false;
			}
			Delegate[] invocationList = jumpEvent.GetInvocationList();
			if (invocationList == null || invocationList.Length == 0)
			{
				return false;
			}
			bool result = false;
			Delegate[] array = invocationList;
			for (int i = 0; i < array.Length; i++)
			{
				ConditionalJumpHandler conditionalJumpHandler = (ConditionalJumpHandler)array[i];
				if (conditionalJumpHandler(((EntityState)self).characterMotor, jumpIgnoredRequirements))
				{
					result = true;
					if (onlyOneJump)
					{
						break;
					}
				}
			}
			return result;
		}
	}
}
public class MoreStatCoefficients
{
	public bool barrierDecayFrozen = false;

	public float barrierGenRate = 0f;

	public float barrierDrainRate = 0f;

	public float barrierDecayMult = 1f;

	public float barrierDecayDynamicHalfLife = 0f;

	public float luckFromBody = 0f;

	public float luckFromMaster = 0f;

	public float burnChance = 0f;

	public bool shieldRechargeReady = true;

	public float shieldRechargeDelay = BaseStats.BaseShieldDelaySeconds;

	public float healthToShieldConversionReversed = 0f;

	public float selfExecutionThresholdAdd = 0f;

	public float selfExecutionThresholdBase = float.NegativeInfinity;

	public float healingMult = 1f;

	public int bodyScrapWhiteCount = 0;

	public int bodyScrapGreenCount = 0;

	public int bodyScrapRedCount = 0;

	public int bodyScrapYellowCount = 0;

	public int maxHealthGateCount = 0;

	public float lowestCombinedHealthFraction = 1f;

	public bool preventHitStun = false;

	public float hitStunThresholdScale = 1f;

	internal float GetNextThresholdHealthFraction()
	{
		if (maxHealthGateCount == 0)
		{
			return -1f;
		}
		int num = maxHealthGateCount + 1;
		return FloorOrSubAndMult(lowestCombinedHealthFraction, num) / (float)num;
		static float FloorOrSubAndMult(float value, float multiplier)
		{
			return Mathf.Ceil(value * multiplier) - 1f;
		}
	}

	internal float GetHealthFractionSize()
	{
		if (maxHealthGateCount == 0)
		{
			return -1f;
		}
		return 1 / (maxHealthGateCount + 1);
	}

	internal void ResetStats()
	{
		barrierDecayFrozen = false;
		barrierDecayDynamicHalfLife = 0f;
		barrierGenRate = 0f;
		luckFromBody = 0f;
		burnChance = 0f;
		shieldRechargeReady = true;
		shieldRechargeDelay = BaseStats.BaseShieldDelaySeconds;
		selfExecutionThresholdAdd = 0f;
		selfExecutionThresholdBase = 0f;
		healingMult = 1f;
		bodyScrapWhiteCount = 0;
		bodyScrapGreenCount = 0;
		bodyScrapRedCount = 0;
		bodyScrapYellowCount = 0;
		maxHealthGateCount = 0;
	}
}
public static class StatHooks
{
	public class MoreStatHookEventArgs
	{
		public int barrierFreezeCount = 0;

		public float barrierDecayRatePercentIncreaseMult = 1f;

		public float barrierDecayRatePercentDecreaseDiv = 1f;

		public float barrierGenerationRateAddPostMult = 0f;

		public float barrierDecayRateAddPreMult = 0f;

		public int jumpCountAdd = 0;

		public float burnChanceOnHit = 0f;

		public float shieldHealthConversionFractionReversedMult = 1f;

		public float shieldDelaySecondsIncreaseAddPreMult = 0f;

		public float shieldDelaySecondsIncreaseAddPostMult = 0f;

		public float shieldDelayPercentIncreaseMult = 1f;

		public float shieldDelayPercentDecreaseDiv = 1f;

		public float luckAdd = 0f;

		public float selfExecutionThresholdAdd = 0f;

		public float healingPercentIncreaseMult = 1f;

		public int scrapWhiteCountAdd = 0;

		public int scrapGreenCountAdd = 0;

		public int scrapRedCountAdd = 0;

		public int scrapYellowCountAdd = 0;

		public int preventHitStunCount = 0;

		public float hitStunThresholdScaleMult = 1f;

		public float barrierDecayMultiplier
		{
			get
			{
				if (barrierDecayRatePercentDecreaseDiv <= 0f || barrierDecayRatePercentIncreaseMult <= 0f)
				{
					return 0f;
				}
				return barrierDecayRatePercentIncreaseMult / barrierDecayRatePercentDecreaseDiv;
			}
		}

		public float shieldDelayMultiplier
		{
			get
			{
				if (shieldDelayPercentDecreaseDiv <= 0f || shieldDelayPercentIncreaseMult <= 0f)
				{
					return 0f;
				}
				return shieldDelayPercentIncreaseMult / shieldDelayPercentDecreaseDiv;
			}
		}

		public float selfExecutionThresholdBase { get; private set; } = float.NegativeInfinity;

		public int maxHealthGateCount { get; private set; } = 0;

		public float ModifyBaseExecutionThreshold(float newThreshold, bool condition)
		{
			if (newThreshold <= 0f || selfExecutionThresholdBase >= 1f)
			{
				return selfExecutionThresholdBase;
			}
			if (condition && newThreshold > selfExecutionThresholdBase)
			{
				selfExecutionThresholdBase = newThreshold;
			}
			return selfExecutionThresholdBase;
		}

		public int ModifyHealthGateCount(int newCount, bool condition = true)
		{
			if (newCount <= 0 || selfExecutionThresholdBase >= 1f)
			{
				return maxHealthGateCount;
			}
			if (condition && newCount > maxHealthGateCount)
			{
				maxHealthGateCount = newCount;
			}
			return maxHealthGateCount;
		}
	}

	public delegate void MoreStatHookEventHandler(CharacterBody sender, MoreStatHookEventArgs args);

	public delegate void HealthGateTriggeredEventHandler(CharacterBody sender);

	private static bool initialized = false;

	public static FixedConditionalWeakTable<CharacterBody, MoreStatCoefficients> characterCustomStats = new FixedConditionalWeakTable<CharacterBody, MoreStatCoefficients>();

	private static MoreStatHookEventArgs StatMods;

	private static MoreStatCoefficients CustomStats;

	public static event MoreStatHookEventHandler GetMoreStatCoefficients;

	public static event HealthGateTriggeredEventHandler OnBodyHealthGateTriggeredGlobal;

	public static MoreStatCoefficients GetMoreStatsFromBody(CharacterBody body)
	{
		if ((Object)(object)body == (Object)null)
		{
			return null;
		}
		return characterCustomStats.GetOrCreateValue(body);
	}

	internal static void Init()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Expected O, but got Unknown
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Expected O, but got Unknown
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Expected O, but got Unknown
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Expected O, but got Unknown
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Expected O, but got Unknown
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Expected O, but got Unknown
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Expected O, but got Unknown
		if (!initialized)
		{
			initialized = true;
			CharacterBody.RecalculateStats += new Manipulator(RecalculateMoreStats);
			CharacterBody.UpdateOutOfCombatAndDanger += new hook_UpdateOutOfCombatAndDanger(UpdateDangerMoreStats);
			Util.CheckRoll_float_float_CharacterMaster += new hook_CheckRoll_float_float_CharacterMaster(RoundLuckInCheckRoll);
			HealthComponent.ServerFixedUpdate += new Manipulator(HookHealthComponentUpdate);
			HealthComponent.GetBarrierDecayRate += new Manipulator(HookBarrierDecayRate);
			HealthComponent.TakeDamageProcess += new Manipulator(InterceptExecutionThreshold);
			HealthComponent.GetHealthBarValues += new hook_GetHealthBarValues(DisplayExecutionThreshold);
			HealthComponent.Heal += new Manipulator(ModifyHealing);
			HealthComponent.TakeDamageProcess += new Manipulator(InsertHealthGates);
			GlobalEventManager.onServerDamageDealt += RecordHealthFractionServer;
			GlobalEventManager.onClientDamageNotified += RecordHealthFractionClient;
			CharacterBody.onBodyStartGlobal += RecordHealthFractionBody;
			SetStateOnHurt.GetShouldHitStun += new hook_GetShouldHitStun(OverrideHitStun);
			DrifterTrashToTreasureController.OnInventoryChanged += new hook_OnInventoryChanged(DrifterUpdateScrapCounts);
		}
	}

	private static bool OverrideHitStun(orig_GetShouldHitStun orig, SetStateOnHurt self, HealthComponent healthComponent, float trueDamage)
	{
		if (Object.op_Implicit((Object)(object)healthComponent.body))
		{
			MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(healthComponent.body);
			if (moreStatsFromBody.preventHitStun)
			{
				return false;
			}
			trueDamage *= moreStatsFromBody.hitStunThresholdScale;
		}
		return orig.Invoke(self, healthComponent, trueDamage);
	}

	private static void HookHealthComponentUpdate(ILContext il)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		ILCursor c = new ILCursor(il);
		ModifyBarrierDecayRate_ServerFixedUpdate(c);
		ModifyShieldRechargeReady(c);
	}

	private static void ModifyHealing(ILContext il)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		ILCursor val = new ILCursor(il);
		int num = default(int);
		if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[2]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 1),
			(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref num)
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("ModifyHealing");
			return;
		}
		int index = val.Index;
		val.Index = index + 1;
		val.Emit(OpCodes.Ldarg_0);
		val.EmitDelegate<Func<float, HealthComponent, float>>((Func<float, HealthComponent, float>)delegate(float healAmt, HealthComponent healthComponent)
		{
			CharacterBody body = healthComponent.body;
			MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(body);
			return (moreStatsFromBody.healingMult > 0f) ? (healAmt * moreStatsFromBody.healingMult) : healAmt;
		});
		val.Emit(OpCodes.Starg, 1);
		val.Emit(OpCodes.Ldarg_1);
	}

	private static void RecalculateMoreStats(ILContext il)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		ILCursor val = new ILCursor(il);
		val.Emit(OpCodes.Ldarg_0);
		val.EmitDelegate<Action<CharacterBody>>((Action<CharacterBody>)GetStatMods);
		val.Emit(OpCodes.Ldarg_0);
		val.EmitDelegate<Action<CharacterBody>>((Action<CharacterBody>)delegate(CharacterBody body)
		{
			CustomStats = GetMoreStatsFromBody(body);
			if (Object.op_Implicit((Object)(object)body.master))
			{
				CharacterMaster master = body.master;
				master.luck -= CustomStats.luckFromBody;
			}
			CustomStats.ResetStats();
			if (Object.op_Implicit((Object)(object)body.master))
			{
				CharacterMaster master2 = body.master;
				master2.luck += StatMods.luckAdd;
				CustomStats.luckFromBody = StatMods.luckAdd;
			}
			CustomStats.burnChance = StatMods.burnChanceOnHit;
			CustomStats.healingMult = StatMods.healingPercentIncreaseMult;
			CustomStats.barrierDecayFrozen = StatMods.barrierFreezeCount > 0;
			CustomStats.barrierDrainRate = StatMods.barrierDecayRateAddPreMult;
			CustomStats.barrierDecayMult = StatMods.barrierDecayMultiplier;
			CustomStats.barrierGenRate = StatMods.barrierGenerationRateAddPostMult;
			float num = (BaseStats.BaseShieldDelaySeconds + StatMods.shieldDelaySecondsIncreaseAddPreMult) * StatMods.shieldDelayMultiplier + StatMods.shieldDelaySecondsIncreaseAddPostMult;
			CustomStats.shieldRechargeDelay = Mathf.Max(BaseStats.MinShieldDelaySeconds, num);
			UpdateShieldRechargeReady(body, CustomStats);
			CustomStats.healthToShieldConversionReversed = 1f - Mathf.Clamp01(StatMods.shieldHealthConversionFractionReversedMult);
			CustomStats.selfExecutionThresholdAdd = StatMods.selfExecutionThresholdAdd;
			CustomStats.selfExecutionThresholdBase = StatMods.selfExecutionThresholdBase;
			CustomStats.maxHealthGateCount = StatMods.maxHealthGateCount;
			CustomStats.hitStunThresholdScale = StatMods.hitStunThresholdScaleMult;
			CustomStats.preventHitStun = StatMods.preventHitStunCount > 0;
		});
		ProcessLuck(val);
		ProcessMaxJumpCount(val);
		ProcessScrapCounts(val);
		if (BaseStats.ApplyShieldConversionHook)
		{
			ProcessShieldConversion(val);
		}
	}

	private static void GetStatMods(CharacterBody body)
	{
		StatMods = new MoreStatHookEventArgs();
		if (StatHooks.GetMoreStatCoefficients != null)
		{
			StatHooks.GetMoreStatCoefficients(body, StatMods);
		}
	}

	private static void ProcessLuck(ILCursor c)
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		c.Index = 0;
		if (!c.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<CharacterMaster>(x, "set_luck")
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("ProcessLuck");
			return;
		}
		c.EmitDelegate<Func<float>>((Func<float>)(() => StatMods.luckAdd));
		c.Emit(OpCodes.Add);
	}

	private static void HookBarrierDecayRate(ILContext il)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		ILCursor val = new ILCursor(il);
		float num = default(float);
		if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[2]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, ref num),
			(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, ref num)
		}))
		{
			val.Remove();
			val.Remove();
			val.Emit(OpCodes.Ldc_R4, BaseStats.BarrierLowDecayFactor);
			val.Emit(OpCodes.Ldc_R4, BaseStats.BarrierHighDecayFactor);
		}
		else
		{
			Debug.LogError((object)"MORE STATS DYNAMIC BARRIER DECAY HOOK FAILED!!!!");
		}
		if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[2]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, ref num),
			(Instruction x) => ILPatternMatchingExt.MatchDiv(x)
		}))
		{
			val.Remove();
			val.Emit(OpCodes.Ldc_R4, BaseStats.BarrierDecayStaticMaxHealthTime);
		}
		else
		{
			Debug.LogError((object)"MORE STATS STATIC BARRIER DECAY HOOK FAILED!!!!");
		}
	}

	private static void ModifyBarrierDecayRate_ServerFixedUpdate(ILCursor c)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		c.Index = 0;
		if (c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<HealthComponent>(x, "GetBarrierDecayRate")
		}))
		{
			c.Emit(OpCodes.Ldarg_0);
			c.EmitDelegate<Func<float, HealthComponent, float>>((Func<float, HealthComponent, float>)delegate(float barrierDecayRatePerSecond, HealthComponent healthComponent)
			{
				MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(healthComponent.body);
				if (moreStatsFromBody == null)
				{
					return barrierDecayRatePerSecond;
				}
				if (!moreStatsFromBody.barrierDecayFrozen)
				{
					barrierDecayRatePerSecond += moreStatsFromBody.barrierDrainRate;
					barrierDecayRatePerSecond *= moreStatsFromBody.barrierDecayMult;
				}
				else
				{
					barrierDecayRatePerSecond = 0f;
				}
				barrierDecayRatePerSecond -= moreStatsFromBody.barrierGenRate;
				return barrierDecayRatePerSecond;
			});
		}
		else
		{
			Debug.LogError((object)"MORE STATS BARRIER DECAY HOOK FAILED!!!!");
		}
	}

	private static void ProcessMaxJumpCount(ILCursor c)
	{
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		c.Index = 0;
		int featherCountLoc = 0;
		if (!c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, "RoR2.RoR2Content/Items", "Feather")
		}) || !c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref featherCountLoc)
		}) || !c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[2]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "baseJumpCount"),
			(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, featherCountLoc)
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("ProcessMaxJumpCount");
			return;
		}
		c.Emit(OpCodes.Ldarg_0);
		c.EmitDelegate<Func<int, CharacterBody, int>>((Func<int, CharacterBody, int>)delegate(int featherCount, CharacterBody self)
		{
			int num = 0;
			MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(self);
			if (featherCount > 0)
			{
				num += BaseStats.FeatherJumpCountBase + BaseStats.FeatherJumpCountStack * (featherCount - 1);
			}
			num += StatMods.jumpCountAdd;
			return Mathf.Max(num, 0);
		});
	}

	private static bool RoundLuckInCheckRoll(orig_CheckRoll_float_float_CharacterMaster orig, float percentChance, float luck, CharacterMaster effectOriginMaster)
	{
		float num = luck % 1f;
		if (num < 0f)
		{
			num += 1f;
		}
		luck = ((!(num > float.Epsilon) || !Util.CheckRoll(num * 100f, 0f, (CharacterMaster)null)) ? ((float)Math.Floor(luck)) : ((float)Math.Ceiling(luck)));
		return orig.Invoke(percentChance, luck, effectOriginMaster);
	}

	private static void UpdateDangerMoreStats(orig_UpdateOutOfCombatAndDanger orig, CharacterBody self)
	{
		orig.Invoke(self);
		MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(self);
		UpdateShieldRechargeReady(self, moreStatsFromBody);
	}

	private static void UpdateShieldRechargeReady(CharacterBody body, MoreStatCoefficients stats)
	{
		bool flag = body.outOfDangerStopwatch >= stats.shieldRechargeDelay;
		if (stats.shieldRechargeReady != flag)
		{
			stats.shieldRechargeReady = flag;
			body.statsDirty = true;
		}
	}

	private static void ModifyShieldRechargeReady(ILCursor c)
	{
		c.Index = 0;
		if (!c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<CharacterBody>(x, "get_maxShield")
		}) || !c.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<CharacterBody>(x, "get_outOfDanger")
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("ModifyShieldRechargeReady");
			return;
		}
		c.Remove();
		c.EmitDelegate<Func<CharacterBody, bool>>((Func<CharacterBody, bool>)delegate(CharacterBody body)
		{
			MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(body);
			return moreStatsFromBody.shieldRechargeReady;
		});
	}

	private static void ProcessShieldConversion(ILCursor c)
	{
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		c.Index = 0;
		ILLabel val = c.DefineLabel();
		int localShieldTotalLoc = 74;
		if (!c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdfld<CharacterBody>(x, "levelMaxShield")
		}) || !c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref localShieldTotalLoc)
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("ProcessShieldConversion", 1);
			return;
		}
		int num = default(int);
		if (!c.TryGotoNext((MoveType)0, new Func<Instruction, bool>[3]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
			(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num),
			(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<CharacterBody>(x, "set_maxShield")
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("ProcessShieldConversion", 2);
			return;
		}
		c.MarkLabel(val);
		int index = c.Index;
		c.Index = index + 1;
		c.EmitDelegate<Func<CharacterBody, float, float>>((Func<CharacterBody, float, float>)ConvertHealthToShield);
		ILLabel val2 = default(ILLabel);
		if (!c.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref val2)
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("ProcessShieldConversion", 3);
			return;
		}
		c.EmitDelegate<Func<bool, bool>>((Func<bool, bool>)((bool _) => false));
		if (!c.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[2]
		{
			(Instruction x) => ILPatternMatchingExt.MatchDup(x),
			(Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref val2)
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("ProcessShieldConversion", 4);
			return;
		}
		c.Remove();
		c.Emit(OpCodes.Ldc_I4_0);
	}

	public static float ConvertHealthToShield(CharacterBody self, float maxShield)
	{
		float healthToShieldConversionReversed = CustomStats.healthToShieldConversionReversed;
		int transCount = self.inventory.GetItemCountEffective(Items.ShieldOnly);
		bool isTrans = transCount > 0;
		bool isPerfected = self.HasBuff(Buffs.AffixLunar);
		bool flag = self.HasBuff(Buffs.AffixBlue);
		healthToShieldConversionReversed *= 1f - GetTransConversion(BaseStats.TranscendenceShieldConversionFractionBase, BaseStats.TranscendenceShieldConversionFractionStack, BaseStats.PerfectedShieldConversionFraction);
		healthToShieldConversionReversed *= 1f - (flag ? BaseStats.OverloadingShieldConversionFraction : 0f);
		float num = GetTransConversion(BaseStats.TranscendenceHealthBonusBase, BaseStats.TranscendenceHealthBonusStack, BaseStats.PerfectedHealthBonus);
		self.maxHealth *= num;
		float num2 = self.maxHealth * (1f - healthToShieldConversionReversed);
		self.maxHealth = ((healthToShieldConversionReversed == 0f) ? 1f : (self.maxHealth - num2));
		return maxShield + num2;
		float GetTransConversion(float transBase, float transStack, float perfected)
		{
			if (!isTrans && !isPerfected)
			{
				return 0f;
			}
			if (isTrans != isPerfected)
			{
				if (isPerfected)
				{
					return perfected;
				}
				return transBase + transStack * (float)(transCount - 1);
			}
			return Mathf.Max(transBase, perfected) + transStack * (float)(transCount - 1);
		}
	}

	private static void InterceptExecutionThreshold(ILContext il)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Expected O, but got Unknown
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: 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)
		ILCursor val = new ILCursor(il);
		int thresholdPosition = 0;
		if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[2]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, float.NegativeInfinity),
			(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref thresholdPosition)
		}) || !val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[2]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
			(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<HealthComponent>(x, "get_isInFrozenState")
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("InterceptExecutionThreshold");
			return;
		}
		val.Emit(OpCodes.Ldloc, thresholdPosition);
		val.Emit(OpCodes.Ldarg, 0);
		val.EmitDelegate<Func<float, HealthComponent, float>>((Func<float, HealthComponent, float>)((float currentThreshold, HealthComponent hc) => RecalculateExecutionThreshold(currentThreshold, hc)));
		val.Emit(OpCodes.Stloc, thresholdPosition);
	}

	private static float RecalculateExecutionThreshold(float currentThreshold, HealthComponent healthComponent, float mult = 1f)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		CharacterBody body = healthComponent.body;
		if ((Object)(object)body != (Object)null && !((Enum)body.bodyFlags).HasFlag((Enum)(object)(BodyFlags)16))
		{
			MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(body);
			float num = Mathf.Max(currentThreshold, moreStatsFromBody.selfExecutionThresholdBase * mult);
			return num + moreStatsFromBody.selfExecutionThresholdAdd;
		}
		return currentThreshold;
	}

	private static HealthBarValues DisplayExecutionThreshold(orig_GetHealthBarValues orig, HealthComponent self)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		HealthBarValues val = orig.Invoke(self);
		val.cullFraction = Mathf.Clamp01(RecalculateExecutionThreshold(val.cullFraction, self, Mathf.Clamp01(1f - (1f - 1f / self.body.cursePenalty))));
		return val;
	}

	private static void ProcessScrapCounts(ILCursor c)
	{
		ProcessScrapCount("ScrapWhite", delegate(int scrapCount, CharacterBody self)
		{
			MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(self);
			moreStatsFromBody.bodyScrapWhiteCount = scrapCount + StatMods.scrapWhiteCountAdd;
			if (BaseStats.IncludeStrangeScrapInScrapTotal)
			{
				moreStatsFromBody.bodyScrapWhiteCount += self.inventory.GetItemCountEffective(Items.ScrapWhiteSuppressed);
			}
			return moreStatsFromBody.bodyScrapWhiteCount;
		});
		ProcessScrapCount("ScrapGreen", delegate(int scrapCount, CharacterBody self)
		{
			MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(self);
			moreStatsFromBody.bodyScrapGreenCount = scrapCount + StatMods.scrapGreenCountAdd;
			if (BaseStats.IncludeStrangeScrapInScrapTotal)
			{
				moreStatsFromBody.bodyScrapGreenCount += self.inventory.GetItemCountEffective(Items.ScrapGreenSuppressed);
			}
			return moreStatsFromBody.bodyScrapGreenCount;
		});
		ProcessScrapCount("ScrapRed", delegate(int scrapCount, CharacterBody self)
		{
			MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(self);
			moreStatsFromBody.bodyScrapRedCount = scrapCount + StatMods.scrapRedCountAdd;
			if (BaseStats.IncludeStrangeScrapInScrapTotal)
			{
				moreStatsFromBody.bodyScrapRedCount += self.inventory.GetItemCountEffective(Items.ScrapRedSuppressed);
			}
			return moreStatsFromBody.bodyScrapRedCount;
		});
		ProcessScrapCount("ScrapYellow", delegate(int scrapCount, CharacterBody self)
		{
			MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(self);
			moreStatsFromBody.bodyScrapYellowCount = scrapCount + StatMods.scrapYellowCountAdd;
			return moreStatsFromBody.bodyScrapYellowCount;
		});
		void ProcessScrapCount(string scrapName, Func<int, CharacterBody, int> callback)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			c.Index = 0;
			if (!c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, "RoR2.RoR2Content/Items", scrapName)
			}) || !c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<Inventory>(x, "GetItemCountEffective")
			}))
			{
				MoreStatsPlugin.DebugBreakpoint("ProcessScrapCount/" + scrapName);
			}
			else
			{
				c.Emit(OpCodes.Ldarg_0);
				c.EmitDelegate<Func<int, CharacterBody, int>>(callback);
			}
		}
	}

	private static void DrifterUpdateScrapCounts(orig_OnInventoryChanged orig, DrifterTrashToTreasureController self)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(self.body);
		self.body.SetBuffCount(Buffs.TrashToTreasureWhite.buffIndex, moreStatsFromBody.bodyScrapWhiteCount);
		self.body.SetBuffCount(Buffs.TrashToTreasureGreen.buffIndex, moreStatsFromBody.bodyScrapGreenCount);
		self.body.SetBuffCount(Buffs.TrashToTreasureRed.buffIndex, moreStatsFromBody.bodyScrapRedCount);
		self.body.SetBuffCount(Buffs.TrashToTreasureYellow.buffIndex, moreStatsFromBody.bodyScrapYellowCount);
	}

	private static void InsertHealthGates(ILContext il)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Expected O, but got Unknown
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		ILCursor val = new ILCursor(il);
		int localDamageLoc = 10;
		ILLabel jumpTo = val.DefineLabel();
		ILLabel val2 = val.DefineLabel();
		if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[2]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdfld<DamageInfo>(x, "damage"),
			(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref localDamageLoc)
		}) || !val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchLdfld<ItemCounts>(x, "minHealthPercentage")
		}) || !val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchBle(x, ref jumpTo)
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("InsertHealthGates", 1);
			return;
		}
		val.GotoLabel(jumpTo, (MoveType)2, false);
		val.Emit(OpCodes.Ldarg_0);
		val.Emit(OpCodes.Ldloc, localDamageLoc);
		val.EmitDelegate<Func<HealthComponent, float, float>>((Func<HealthComponent, float, float>)delegate(HealthComponent self, float damageIn)
		{
			if (self.itemCounts.minHealthPercentage > 0 || (Object)(object)self.body == (Object)null)
			{
				return damageIn;
			}
			MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(self.body);
			if (moreStatsFromBody.maxHealthGateCount <= 0)
			{
				return damageIn;
			}
			float nextThresholdHealthFraction = moreStatsFromBody.GetNextThresholdHealthFraction();
			if (nextThresholdHealthFraction < moreStatsFromBody.GetHealthFractionSize() || nextThresholdHealthFraction <= 0.02f)
			{
				return damageIn;
			}
			float num = self.combinedHealth - self.fullCombinedHealth * nextThresholdHealthFraction;
			if (damageIn < num)
			{
				return damageIn;
			}
			RecordBodyLowestHealth(moreStatsFromBody, nextThresholdHealthFraction - 0.01f);
			if (StatHooks.OnBodyHealthGateTriggeredGlobal != null)
			{
				StatHooks.OnBodyHealthGateTriggeredGlobal(self.body);
			}
			return num;
		});
		val.Emit(OpCodes.Stloc, localDamageLoc);
	}

	private static void DisplayHealthGates(ILContext il)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		ILCursor val = new ILCursor(il);
		if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
		{
			(Instruction x) => ILPatternMatchingExt.MatchStfld<HealthBarValues>(x, "ospFraction")
		}))
		{
			MoreStatsPlugin.DebugBreakpoint("DisplayHealthGates");
			return;
		}
		val.Emit(OpCodes.Ldarg_0);
		val.EmitDelegate<Func<float, HealthComponent, float>>((Func<float, HealthComponent, float>)delegate(float ospFractionIn, HealthComponent self)
		{
			float num = GetNewFraction();
			Debug.Log((object)num);
			return num;
			float GetNewFraction()
			{
				if ((Object)(object)self.body == (Object)null)
				{
					return ospFractionIn;
				}
				MoreStatCoefficients moreStatsFromBody = GetMoreStatsFromBody(self.body);
				float nextThresholdHealthFraction = moreStatsFromBody.GetNextThresholdHealthFraction();
				if (nextThresholdHealthFraction < moreStatsFromBody.GetHealthFractionSize())
				{
					return ospFractionIn;
				}
				float num2 = nextThresholdHealthFraction * (1f - 1f / self.body.cursePenalty);
				if (num2 < ospFractionIn)
				{
					return ospFractionIn;
				}
				return nextThresholdHealthFraction;
			}
		});
	}

	private static void RecordHealthFractionBody(CharacterBody obj)
	{
		RecordBodyLowestHealth(obj);
	}

	private static void RecordHealthFractionClient(DamageDealtMessage damageDealtMessage)
	{
		CharacterBody victimBody = default(CharacterBody);
		if (Object.op_Implicit((Object)(object)damageDealtMessage.victim) && damageDealtMessage.victim.TryGetComponent<CharacterBody>(ref victimBody))
		{
			RecordBodyLowestHealth(victimBody);
		}
	}

	private static void RecordHealthFractionServer(DamageReport damageReport)
	{
		RecordBodyLowestHealth(damageReport.victimBody);
	}

	private static void RecordBodyLowestHealth(CharacterBody victimBody)
	{
		if (!((Object)(object)victimBody == (Object)null))
		{
			RecordBodyLowestHealth(GetMoreStatsFromBody(victimBody), victimBody.healthComponent.combinedHealthFraction);
		}
	}

	private static void RecordBodyLowestHealth(MoreStatCoefficients statCoefficients, float healthFraction)
	{
		if (statCoefficients != null)
		{
			statCoefficients.lowestCombinedHealthFraction = Mathf.Min(statCoefficients.lowestCombinedHealthFraction, healthFraction);
		}
	}
}