Decompiled source of WiresCombatFlow v2.1.0

WiresCombatFlow.dll

Decompiled 4 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("WiresCombatFlow")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WiresCombatFlow")]
[assembly: AssemblyTitle("WiresCombatFlow")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WiresCombatFlow
{
	internal static class AutoVerticalAim
	{
		private const int MaxColliders = 48;

		private static readonly Collider[] Nearby = (Collider[])(object)new Collider[48];

		private static readonly int CharacterMask = LayerMask.GetMask(new string[6] { "character", "character_net", "character_ghost", "hitbox", "character_noenv", "vehicle" });

		private static readonly int WorldMask = LayerMask.GetMask(new string[6] { "Default", "Default_small", "static_solid", "piece", "terrain", "blocker" });

		private static readonly FieldRef<Attack, Humanoid> Attacker = AccessTools.FieldRefAccess<Attack, Humanoid>("m_character");

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> MaxCorrection;

		internal static ConfigEntry<float> HorizontalCone;

		[ThreadStatic]
		private static Attack _evaluatingHit;

		internal static void Bind(ConfigFile file)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			Enabled = file.Bind<bool>("Vertical Melee Aim", "Enabled", true, "Automatically correct only the invisible vertical hit direction toward an enemy in the existing melee attack arc.");
			MaxCorrection = file.Bind<float>("Vertical Melee Aim", "Maximum Correction Angle", 65f, new ConfigDescription("Maximum absolute up/down hit angle in degrees. No extra reach or wider horizontal attack arc.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 85f), Array.Empty<object>()));
			HorizontalCone = file.Bind<float>("Vertical Melee Aim", "Search Cone Half Angle", 25f, new ConfigDescription("Maximum sideways angle for identifying a target. It never exceeds the weapon's normal horizontal attack arc.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 45f), Array.Empty<object>()));
		}

		internal static void BeginHit(Attack attack)
		{
			_evaluatingHit = attack;
		}

		internal static void EndHit()
		{
			_evaluatingHit = null;
		}

		internal static void CorrectDirection(Attack attack, Transform originJoint, ref Vector3 direction)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Invalid comparison between Unknown and I4
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0617: Unknown result type (might be due to invalid IL or missing references)
			//IL_0627: Unknown result type (might be due to invalid IL or missing references)
			//IL_0630: Unknown result type (might be due to invalid IL or missing references)
			//IL_0635: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03be: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_047e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_051f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0521: Unknown result type (might be due to invalid IL or missing references)
			//IL_0524: Unknown result type (might be due to invalid IL or missing references)
			//IL_0529: Unknown result type (might be due to invalid IL or missing references)
			//IL_052e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0535: Unknown result type (might be due to invalid IL or missing references)
			//IL_053d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0542: Unknown result type (might be due to invalid IL or missing references)
			//IL_0547: Unknown result type (might be due to invalid IL or missing references)
			//IL_0549: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0557: Unknown result type (might be due to invalid IL or missing references)
			//IL_055c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0562: Unknown result type (might be due to invalid IL or missing references)
			//IL_056e: Unknown result type (might be due to invalid IL or missing references)
			//IL_057d: Unknown result type (might be due to invalid IL or missing references)
			if (_evaluatingHit != attack || Enabled == null || !Enabled.Value || MaxCorrection.Value <= 0f || (Object)(object)originJoint == (Object)null || attack == null || ((int)attack.m_attackType != 0 && (int)attack.m_attackType != 1) || attack.m_isHomeItem || attack.m_harvest || attack.m_pickaxeSpecial)
			{
				return;
			}
			Humanoid obj = Attacker.Invoke(attack);
			Player val = (Player)(object)((obj is Player) ? obj : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || ((Character)val).IsDead() || ((Character)val).InPlaceMode())
			{
				return;
			}
			ItemData weapon = attack.GetWeapon();
			if (weapon == null || weapon.m_shared.m_tamedOnly)
			{
				return;
			}
			Transform transform = ((Component)val).transform;
			Vector3 forward = transform.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
			{
				return;
			}
			((Vector3)(ref forward)).Normalize();
			Vector3 val2 = originJoint.position + Vector3.up * attack.m_attackHeight + transform.right * attack.m_attackOffset;
			float num = Mathf.Max(0f, attack.m_attackRange);
			if (num <= 0.05f)
			{
				return;
			}
			int characterMask = CharacterMask;
			float num2 = Mathf.Max(attack.m_attackRayWidth, attack.m_attackRayWidth + attack.m_attackRayWidthCharExtra);
			num2 = Mathf.Max(0f, num2);
			float num3 = num + num2 + Mathf.Max(Mathf.Abs(attack.m_attackHeightChar1), Mathf.Abs(attack.m_attackHeightChar2));
			float num4 = (((int)attack.m_attackType == 1) ? 0f : Mathf.Min(HorizontalCone.Value, Mathf.Max(0f, attack.m_attackAngle * 0.5f)));
			int num5 = Physics.OverlapSphereNonAlloc(val2, num3, Nearby, characterMask, (QueryTriggerInteraction)1);
			if (num5 <= 0 || num5 >= Nearby.Length)
			{
				return;
			}
			float num6 = float.MaxValue;
			Vector3 val3 = Vector3.zero;
			Vector3 val4 = Vector3.zero;
			Vector3 zero = Vector3.zero;
			bool flag = false;
			for (int i = 0; i < num5; i++)
			{
				Collider val5 = Nearby[i];
				if ((Object)(object)val5 == (Object)null || !val5.enabled)
				{
					continue;
				}
				GameObject val6 = Projectile.FindHitObject(val5);
				Character val7 = (((Object)(object)val6 != (Object)null) ? val6.GetComponent<Character>() : null);
				if ((Object)(object)val7 == (Object)null)
				{
					val7 = ((Component)val5).GetComponentInParent<Character>();
				}
				if ((Object)(object)val7 == (Object)null || (Object)(object)val7 == (Object)(object)val || val7.IsDead())
				{
					continue;
				}
				BaseAI baseAI = val7.GetBaseAI();
				if (!BaseAI.IsEnemy((Character)(object)val, val7) && ((Object)(object)baseAI == (Object)null || !baseAI.IsAggravatable()))
				{
					continue;
				}
				Bounds bounds = val5.bounds;
				Vector3 val8 = ((Bounds)(ref bounds)).center - val2;
				val8.y = 0f;
				float sqrMagnitude = ((Vector3)(ref val8)).sqrMagnitude;
				if (sqrMagnitude < 0.0004f)
				{
					continue;
				}
				float num7 = Vector3.Dot(val8, forward);
				if (num7 <= 0.01f)
				{
					continue;
				}
				float num8 = Mathf.Abs(Vector3.Dot(val8, transform.right));
				float num9 = Mathf.Abs(transform.right.x) * ((Bounds)(ref bounds)).extents.x + Mathf.Abs(transform.right.z) * ((Bounds)(ref bounds)).extents.z + num2;
				float num10 = Mathf.Atan2(num8, num7) * 57.29578f;
				float num11 = Mathf.Atan2(num9, Mathf.Max(0.1f, num7)) * 57.29578f;
				if (num10 > num4 + num11)
				{
					continue;
				}
				float num12 = num7 / Mathf.Sqrt(sqrMagnitude);
				Vector3 val9 = val5.ClosestPoint(val2);
				Vector3 val10 = val9 - val2;
				float num13 = num + num2;
				float sqrMagnitude2 = ((Vector3)(ref val10)).sqrMagnitude;
				Vector3 val11 = val9 - val2 - Vector3.up * attack.m_attackHeightChar1;
				float num14 = Mathf.Min(sqrMagnitude2, ((Vector3)(ref val11)).sqrMagnitude);
				val11 = val9 - val2 - Vector3.up * attack.m_attackHeightChar2;
				if (Mathf.Min(num14, ((Vector3)(ref val11)).sqrMagnitude) > num13 * num13)
				{
					continue;
				}
				float num15 = Mathf.Min(0.1f, Mathf.Max(0f, ((Bounds)(ref bounds)).size.y * 0.2f));
				float num16 = ((Bounds)(ref bounds)).min.y + num15;
				float num17 = ((Bounds)(ref bounds)).max.y - num15;
				float num18 = Mathf.Clamp(val2.y, num16, num17);
				Vector3 val12 = ((Bounds)(ref bounds)).ClosestPoint(val2) - val2;
				val12.y = 0f;
				float num19 = ((Vector3)(ref val12)).magnitude;
				if (num19 < 0.1f)
				{
					num19 = Mathf.Sqrt(sqrMagnitude);
				}
				num19 = Mathf.Min(Mathf.Sqrt(sqrMagnitude), num19 + 0.08f);
				if (!(Mathf.Abs(Mathf.Atan2(num18 - val2.y, Mathf.Max(0.1f, num19)) * 57.29578f) > MaxCorrection.Value))
				{
					float num20 = ((Vector3)(ref val10)).sqrMagnitude * (1f + (1f - num12) * 5f);
					if (!(num20 >= num6))
					{
						num6 = num20;
						val3 = val2 + forward * num19 + Vector3.up * (num18 - val2.y);
						val4 = Vector3.Lerp(val9, ((Bounds)(ref bounds)).center, 0.65f);
						((Vector3)(ref zero))..ctor(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y - num15, ((Bounds)(ref bounds)).center.z);
						flag = true;
					}
				}
			}
			if (flag && (attack.m_hitThroughWalls || !Physics.Linecast(val2, val4, WorldMask, (QueryTriggerInteraction)1) || !Physics.Linecast(val2, zero, WorldMask, (QueryTriggerInteraction)1)))
			{
				Vector3 val13 = val3 - val2;
				float y = val13.y;
				Vector2 val14 = new Vector2(val13.x, val13.z);
				float num21 = Mathf.Atan2(y, Mathf.Max(0.1f, ((Vector2)(ref val14)).magnitude));
				float num22 = Mathf.Cos(num21);
				direction = new Vector3(forward.x * num22, Mathf.Sin(num21), forward.z * num22);
			}
		}
	}
	[HarmonyPatch(typeof(Attack), "DoMeleeAttack")]
	internal static class MeleeHitContextPatch
	{
		[HarmonyPrefix]
		private static void Prefix(Attack __instance)
		{
			AutoVerticalAim.BeginHit(__instance);
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			AutoVerticalAim.EndHit();
		}

		[HarmonyFinalizer]
		private static Exception Finalizer(Exception __exception)
		{
			AutoVerticalAim.EndHit();
			return __exception;
		}
	}
	[HarmonyPatch(typeof(Attack), "GetMeleeAttackDir")]
	internal static class MeleeHitDirectionPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Attack __instance, Transform originJoint, ref Vector3 attackDir)
		{
			AutoVerticalAim.CorrectDirection(__instance, originJoint, ref attackDir);
		}
	}
	internal static class FlowEnhancements
	{
		private sealed class InputState
		{
			internal float JumpBufferUntil = -100f;

			internal float SprintBufferUntil = -100f;

			internal bool WasRunning;

			internal Animator Animator;

			internal int[] ReturnStateHashes;
		}

		private static ConditionalWeakTable<Player, InputState> States = new ConditionalWeakTable<Player, InputState>();

		internal static void Reset()
		{
			States = new ConditionalWeakTable<Player, InputState>();
		}

		internal static void OnAttackStarted(Player player)
		{
			if (CombatFlow.IsLocal(player))
			{
				CaptureNeutralAnimation(player);
			}
		}

		internal static void CaptureNeutralAnimation(Player player)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			if (!CombatFlow.IsLocal(player) || !Plugin.Enabled.Value || ((Character)player).IsDead() || ((Character)player).IsStaggering() || ((Character)player).InDodge())
			{
				return;
			}
			InputState orCreateValue = States.GetOrCreateValue(player);
			Animator val = orCreateValue.Animator;
			if ((Object)(object)val == (Object)null)
			{
				val = (orCreateValue.Animator = ((Component)player).GetComponentInChildren<Animator>(true));
			}
			if ((Object)(object)val == (Object)null || ((Character)player).InAttack())
			{
				return;
			}
			if (orCreateValue.ReturnStateHashes == null || orCreateValue.ReturnStateHashes.Length != val.layerCount)
			{
				orCreateValue.ReturnStateHashes = new int[val.layerCount];
			}
			for (int i = 0; i < val.layerCount; i++)
			{
				if (!val.IsInTransition(i))
				{
					AnimatorStateInfo currentAnimatorStateInfo = val.GetCurrentAnimatorStateInfo(i);
					if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash != 0 && !((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsTag("attack") && !((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsTag("dodge") && !((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsTag("stagger"))
					{
						orCreateValue.ReturnStateHashes[i] = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash;
					}
				}
			}
		}

		internal static void OnCancelled(Player player, DefensiveCancel kind)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if (!CombatFlow.IsLocal(player))
			{
				return;
			}
			InputState orCreateValue = States.GetOrCreateValue(player);
			Animator val = orCreateValue.Animator;
			if ((Object)(object)val == (Object)null)
			{
				val = (orCreateValue.Animator = ((Component)player).GetComponentInChildren<Animator>(true));
			}
			int[] returnStateHashes = orCreateValue.ReturnStateHashes;
			if ((Object)(object)val == (Object)null || returnStateHashes == null)
			{
				return;
			}
			float value = Plugin.CancelBlendTime.Value;
			int num = Mathf.Min(val.layerCount, returnStateHashes.Length);
			for (int i = 0; i < num; i++)
			{
				int num2 = returnStateHashes[i];
				if (num2 != 0 && val.HasState(i, num2))
				{
					AnimatorStateInfo currentAnimatorStateInfo = val.GetCurrentAnimatorStateInfo(i);
					AnimatorStateInfo val2 = (val.IsInTransition(i) ? val.GetNextAnimatorStateInfo(i) : currentAnimatorStateInfo);
					if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsTag("attack") || ((AnimatorStateInfo)(ref val2)).IsTag("attack"))
					{
						val.CrossFadeInFixedTime(num2, value, i);
					}
				}
			}
			orCreateValue.JumpBufferUntil = -100f;
			orCreateValue.SprintBufferUntil = -100f;
		}

		internal static void BeforeControls(Player player, Vector3 movedir, bool blockHold, ref bool jump, bool run, bool dodge)
		{
			if (!CombatFlow.IsLocal(player) || !Plugin.Enabled.Value)
			{
				return;
			}
			InputState orCreateValue = States.GetOrCreateValue(player);
			if (InventoryGui.IsVisible() || Menu.IsVisible() || Console.IsVisible() || Hud.InRadial())
			{
				orCreateValue.JumpBufferUntil = -100f;
				orCreateValue.SprintBufferUntil = -100f;
				orCreateValue.WasRunning = false;
				return;
			}
			float time = Time.time;
			bool flag = ((Vector3)(ref movedir)).sqrMagnitude > 0.04f;
			bool num = run && !orCreateValue.WasRunning && flag;
			orCreateValue.WasRunning = run;
			bool flag2 = CombatFlow.IsWindup(player);
			bool flag3 = CombatFlow.IsCommittedRecovery(player);
			float value = Plugin.InputBufferDuration.Value;
			float num2 = (flag3 ? CombatFlow.RecoveryElapsed(player) : (-1f));
			bool flag4 = flag3 && num2 < Plugin.RecoveryCancelDelay.Value;
			if (jump && (flag2 || flag4) && !dodge && !blockHold && !((Character)player).IsCrouching())
			{
				float num3 = (flag4 ? (Plugin.RecoveryCancelDelay.Value - num2 + 0.03f) : 0f);
				orCreateValue.JumpBufferUntil = time + Mathf.Max(value, num3);
			}
			else if (jump)
			{
				orCreateValue.JumpBufferUntil = -100f;
			}
			if (!jump && orCreateValue.JumpBufferUntil >= time && flag3 && ((Character)player).IsOnGround() && CombatFlow.RecoveryElapsed(player) >= Plugin.RecoveryCancelDelay.Value)
			{
				jump = true;
				orCreateValue.JumpBufferUntil = -100f;
			}
			else if (orCreateValue.JumpBufferUntil < time)
			{
				orCreateValue.JumpBufferUntil = -100f;
			}
			if (num && (flag2 || flag3))
			{
				float num4 = (flag4 ? (Plugin.RecoveryCancelDelay.Value - num2 + 0.03f) : 0f);
				orCreateValue.SprintBufferUntil = time + Mathf.Max(value, num4);
			}
			if (flag && run && flag3 && !dodge && !blockHold && orCreateValue.SprintBufferUntil >= time && CombatFlow.RecoveryElapsed(player) >= Plugin.RecoveryCancelDelay.Value)
			{
				CombatFlow.BeforeSprint(player);
				orCreateValue.SprintBufferUntil = -100f;
			}
			else if (!run || !flag || orCreateValue.SprintBufferUntil < time)
			{
				orCreateValue.SprintBufferUntil = -100f;
			}
		}

		internal static void SmoothMovement(Player player, ref float movementFactor, bool turning)
		{
			if (!CombatFlow.IsLocal(player) || !Plugin.Enabled.Value)
			{
				return;
			}
			float num = Mathf.Max(0.45f, Plugin.MovementRecoveryTime.Value);
			float num2 = CombatFlow.SprintReleaseElapsed(player);
			if (!turning && num2 >= 0f && ((Character)player).IsRunning())
			{
				float num3 = Mathf.Clamp01(num2 / num);
				num3 = num3 * num3 * (3f - 2f * num3);
				float num4 = Mathf.Lerp(0.24f, 1f, num3);
				movementFactor = Mathf.Min(movementFactor, num4);
				return;
			}
			float num5 = CombatFlow.RecoveryElapsed(player);
			float value = Plugin.RecoveryCancelDelay.Value;
			if (!(num5 <= value) && !(movementFactor >= 1f))
			{
				float num6 = Mathf.Clamp01((num5 - value) / num);
				num6 = num6 * num6 * (3f - 2f * num6);
				if (turning)
				{
					movementFactor = Mathf.Min(1f, movementFactor + (1f - movementFactor) * 0.35f * num6);
				}
				else
				{
					movementFactor = Mathf.Min(1f, movementFactor * (1f + 0.35f * num6));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "SetControls")]
	internal static class InputBufferPatch
	{
		[HarmonyPrefix]
		private static void Prefix(Player __instance, Vector3 movedir, bool blockHold, ref bool jump, bool run, bool dodge)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			FlowEnhancements.BeforeControls(__instance, movedir, blockHold, ref jump, run, dodge);
		}
	}
	[HarmonyPatch(typeof(PlayerController), "FixedUpdate")]
	internal static class NeutralAnimationCapturePatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				FlowEnhancements.CaptureNeutralAnimation(Player.m_localPlayer);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "GetAttackSpeedFactorMovement")]
	internal static class MovementRecoveryPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Humanoid __instance, ref float __result)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val != (Object)null)
			{
				FlowEnhancements.SmoothMovement(val, ref __result, turning: false);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "GetAttackSpeedFactorRotation")]
	internal static class RotationRecoveryPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Humanoid __instance, ref float __result)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val != (Object)null)
			{
				FlowEnhancements.SmoothMovement(val, ref __result, turning: true);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "OnWeaponTrailStart")]
	internal static class CancelledTrailGuardPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(Humanoid __instance)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (!((Object)(object)val == (Object)null))
			{
				return !CombatFlow.BlocksAttackTrigger(val);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Attack), "OnAttackTrigger")]
	internal static class CancelledHitGuardPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(Attack __instance)
		{
			return !CombatFlow.BlocksCancelledAttack(__instance);
		}
	}
	[HarmonyPatch(typeof(Attack), "Start")]
	internal static class ComboGracePatch
	{
		[HarmonyPrefix]
		private static void Prefix(Attack __instance, Humanoid character, Attack previousAttack, ref float timeSinceLastAttack)
		{
			Player val = (Player)(object)((character is Player) ? character : null);
			if (val != null && CombatFlow.IsLocal(val) && Plugin.Enabled.Value && __instance.m_attackChainLevels > 1 && previousAttack != null && !(previousAttack.m_attackAnimation != __instance.m_attackAnimation))
			{
				float value = Plugin.ComboGrace.Value;
				if (timeSinceLastAttack > 0.2f && timeSinceLastAttack <= 0.2f + value)
				{
					timeSinceLastAttack = 0.199f;
				}
			}
		}
	}
	[BepInPlugin("wire.valheim.combatflow", "Wire's Combat Flow", "2.1.0")]
	[BepInProcess("valheim.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "wire.valheim.combatflow";

		public const string Name = "Wire's Combat Flow";

		public const string Version = "2.1.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> RecoveryCancelDelay;

		internal static ConfigEntry<float> BlockCancelCost;

		internal static ConfigEntry<float> DodgeCancelCost;

		internal static ConfigEntry<float> JumpCancelCost;

		internal static ConfigEntry<float> SecondaryExtraCost;

		internal static ConfigEntry<float> SprintCancelCost;

		internal static ConfigEntry<float> InputBufferDuration;

		internal static ConfigEntry<float> ComboGrace;

		internal static ConfigEntry<float> MovementRecoveryTime;

		internal static ConfigEntry<float> CancelBlendTime;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Expected O, but got Unknown
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Expected O, but got Unknown
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Expected O, but got Unknown
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Expected O, but got Unknown
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Expected O, but got Unknown
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable responsive defensive recovery cancels.");
			RecoveryCancelDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Recovery Cancelling", "Delay After Hit", 0.16f, new ConfigDescription("Follow-through time after the attack's actual hit/projectile trigger before recovery may be cancelled.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.4f), Array.Empty<object>()));
			BlockCancelCost = ((BaseUnityPlugin)this).Config.Bind<float>("Recovery Cancelling", "Block Cancel Extra Stamina", 4f, new ConfigDescription("Extra stamina charged when cancelling attack recovery into block.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>()));
			DodgeCancelCost = ((BaseUnityPlugin)this).Config.Bind<float>("Recovery Cancelling", "Dodge Cancel Extra Stamina", 8f, new ConfigDescription("Extra stamina charged when cancelling attack recovery into dodge. The normal dodge stamina cost is still paid too.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>()));
			JumpCancelCost = ((BaseUnityPlugin)this).Config.Bind<float>("Recovery Cancelling", "Jump Cancel Extra Stamina", 6f, new ConfigDescription("Extra stamina charged for jumping out of committed attack recovery, in addition to the normal jump stamina.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>()));
			SecondaryExtraCost = ((BaseUnityPlugin)this).Config.Bind<float>("Recovery Cancelling", "Secondary Attack Extra Stamina", 4f, new ConfigDescription("Additional cancel surcharge after a secondary/special attack.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>()));
			SprintCancelCost = ((BaseUnityPlugin)this).Config.Bind<float>("Recovery Cancelling", "Sprint Cancel Extra Stamina", 6f, new ConfigDescription("Extra stamina for sprinting out of recovery.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>()));
			InputBufferDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Flow", "Input Buffer Seconds", 0.15f, new ConfigDescription("Brief grace period for early jump/sprint inputs.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.3f), Array.Empty<object>()));
			ComboGrace = ((BaseUnityPlugin)this).Config.Bind<float>("Flow", "Extra Combo Grace Seconds", 0.12f, new ConfigDescription("Extra time for continuing the same melee combo after the previous attack ends.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.3f), Array.Empty<object>()));
			MovementRecoveryTime = ((BaseUnityPlugin)this).Config.Bind<float>("Flow", "Movement Recovery Seconds", 0.5f, new ConfigDescription("Duration of gradual post-hit movement and turning easing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 1f), Array.Empty<object>()));
			CancelBlendTime = ((BaseUnityPlugin)this).Config.Bind<float>("Flow", "Cancel Animation Blend Seconds", 0.2f, new ConfigDescription("Smooth transition duration when leaving a cancelled attack.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.08f, 0.35f), Array.Empty<object>()));
			AutoVerticalAim.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("wire.valheim.combatflow");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Wire's Combat Flow 2.1.0 loaded.");
		}

		private void OnDestroy()
		{
			CombatFlow.Reset();
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
			Log = null;
		}
	}
	internal enum DefensiveCancel
	{
		None,
		Block,
		Dodge,
		Jump,
		Sprint
	}
	internal static class CombatFlow
	{
		private sealed class State
		{
			internal Attack Attack;

			internal bool Secondary;

			internal bool Committed;

			internal float CommitTime;

			internal bool SuppressAttack;

			internal Attack CancelledAttack;

			internal float SuppressUntil;

			internal float SprintCancelledAt = -100f;

			internal DefensiveCancel Cancel;
		}

		private static ConditionalWeakTable<Player, State> States = new ConditionalWeakTable<Player, State>();

		private static readonly FieldRef<Humanoid, Attack> CurrentAttack = AccessTools.FieldRefAccess<Humanoid, Attack>("m_currentAttack");

		private static readonly FieldRef<Humanoid, bool> CurrentAttackIsSecondary = AccessTools.FieldRefAccess<Humanoid, bool>("m_currentAttackIsSecondary");

		private static readonly FieldRef<Player, float> QueuedDodgeTimer = AccessTools.FieldRefAccess<Player, float>("m_queuedDodgeTimer");

		private static readonly FieldRef<Player, float> QueuedAttackTimer = AccessTools.FieldRefAccess<Player, float>("m_queuedAttackTimer");

		private static readonly FieldRef<Player, float> QueuedSecondAttackTimer = AccessTools.FieldRefAccess<Player, float>("m_queuedSecondAttackTimer");

		private static readonly FieldRef<Character, bool> Blocking = AccessTools.FieldRefAccess<Character, bool>("m_blocking");

		private static readonly MethodInfo GetDodgeStaminaUseMethod = AccessTools.Method(typeof(Player), "GetDodgeStaminaUse", (Type[])null, (Type[])null);

		internal static bool IsLocal(Player player)
		{
			if ((Object)(object)player != (Object)null)
			{
				return (Object)(object)player == (Object)(object)Player.m_localPlayer;
			}
			return false;
		}

		internal static void AttackStarted(Player player)
		{
			if (IsLocal(player))
			{
				State orCreateValue = States.GetOrCreateValue(player);
				orCreateValue.Attack = CurrentAttack.Invoke((Humanoid)(object)player);
				orCreateValue.Secondary = CurrentAttackIsSecondary.Invoke((Humanoid)(object)player);
				orCreateValue.Committed = false;
				orCreateValue.CommitTime = 0f;
				orCreateValue.SuppressAttack = false;
				orCreateValue.CancelledAttack = null;
				orCreateValue.SuppressUntil = 0f;
				orCreateValue.SprintCancelledAt = -100f;
				orCreateValue.Cancel = DefensiveCancel.None;
				FlowEnhancements.OnAttackStarted(player);
			}
		}

		internal static void AttackTriggered(Player player)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			if (!IsLocal(player))
			{
				return;
			}
			Attack val = CurrentAttack.Invoke((Humanoid)(object)player);
			if (val != null && (int)val.m_attackType != 3)
			{
				State orCreateValue = States.GetOrCreateValue(player);
				if (orCreateValue.Attack != val)
				{
					orCreateValue.Attack = val;
					orCreateValue.Secondary = CurrentAttackIsSecondary.Invoke((Humanoid)(object)player);
					orCreateValue.Committed = false;
					orCreateValue.SuppressAttack = false;
					orCreateValue.CancelledAttack = null;
					orCreateValue.Cancel = DefensiveCancel.None;
				}
				if (!orCreateValue.Committed)
				{
					orCreateValue.Committed = true;
					orCreateValue.CommitTime = Time.time;
				}
			}
		}

		internal static void BeforeDodge(Player player)
		{
			if (IsLocal(player) && Plugin.Enabled != null && Plugin.Enabled.Value && !(QueuedDodgeTimer.Invoke(player) <= 0f))
			{
				TryCancel(player, DefensiveCancel.Dodge);
			}
		}

		internal static void BeforeJump(Player player, bool force)
		{
			if (!(!IsLocal(player) || force) && Plugin.Enabled != null && Plugin.Enabled.Value && !(QueuedDodgeTimer.Invoke(player) > 0f) && ((Character)player).IsOnGround() && !((Character)player).IsEncumbered() && !((Character)player).IsDead() && !((Character)player).InDodge() && !((Character)player).IsKnockedBack() && !((Character)player).IsStaggering() && !((Character)player).IsAttached())
			{
				TryCancel(player, DefensiveCancel.Jump);
			}
		}

		internal static void BeforeBlock(Player player)
		{
			if (IsLocal(player) && Plugin.Enabled != null && Plugin.Enabled.Value && !(QueuedDodgeTimer.Invoke(player) > 0f) && Blocking.Invoke((Character)(object)player))
			{
				TryCancel(player, DefensiveCancel.Block);
			}
		}

		internal static bool IsWindup(Player player)
		{
			if (!IsLocal(player) || !Plugin.Enabled.Value)
			{
				return false;
			}
			if (States.TryGetValue(player, out var value) && value.Attack != null && !value.Attack.IsDone() && !value.Committed && !value.SuppressAttack)
			{
				return CurrentAttack.Invoke((Humanoid)(object)player) == value.Attack;
			}
			return false;
		}

		internal static bool IsCommittedRecovery(Player player)
		{
			if (!IsLocal(player) || !Plugin.Enabled.Value)
			{
				return false;
			}
			if (States.TryGetValue(player, out var value) && value.Committed && value.Attack != null && !value.Attack.IsDone() && !value.SuppressAttack)
			{
				return CurrentAttack.Invoke((Humanoid)(object)player) == value.Attack;
			}
			return false;
		}

		internal static float RecoveryElapsed(Player player)
		{
			if (!IsCommittedRecovery(player) || !States.TryGetValue(player, out var value))
			{
				return -1f;
			}
			return Mathf.Max(0f, Time.time - value.CommitTime);
		}

		internal static float SprintReleaseElapsed(Player player)
		{
			if (!IsLocal(player))
			{
				return -1f;
			}
			if (!States.TryGetValue(player, out var value))
			{
				return -1f;
			}
			float num = Time.time - value.SprintCancelledAt;
			if (!(num >= 0f) || !(num <= Mathf.Max(0.45f, Plugin.MovementRecoveryTime.Value)))
			{
				return -1f;
			}
			return num;
		}

		internal static bool BlocksAttackTrigger(Player player)
		{
			if (!IsLocal(player))
			{
				return false;
			}
			if (States.TryGetValue(player, out var value) && value.CancelledAttack != null)
			{
				return CurrentAttack.Invoke((Humanoid)(object)player) == value.CancelledAttack;
			}
			return false;
		}

		internal static bool BlocksCancelledAttack(Attack attack)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || attack == null)
			{
				return false;
			}
			if (States.TryGetValue(localPlayer, out var value))
			{
				return value.CancelledAttack == attack;
			}
			return false;
		}

		internal static void BeforeSprint(Player player)
		{
			if (IsCommittedRecovery(player) && QueuedDodgeTimer.Invoke(player) <= 0f && !Blocking.Invoke((Character)(object)player))
			{
				TryCancel(player, DefensiveCancel.Sprint);
			}
		}

		private static void TryCancel(Player player, DefensiveCancel cancel)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			State orCreateValue = States.GetOrCreateValue(player);
			Attack val = CurrentAttack.Invoke((Humanoid)(object)player);
			if (orCreateValue.SuppressAttack || val == null || val != orCreateValue.Attack || val.IsDone() || (int)val.m_attackType == 3 || val.m_attackKillsSelf || ((Character)player).InPlaceMode() || ((Character)player).IsDead() || ((Character)player).InDodge() || ((Character)player).IsStaggering() || ((Character)player).IsKnockedBack() || !orCreateValue.Committed || Time.time - orCreateValue.CommitTime < Plugin.RecoveryCancelDelay.Value)
			{
				return;
			}
			float num = cancel switch
			{
				DefensiveCancel.Dodge => Plugin.DodgeCancelCost.Value, 
				DefensiveCancel.Jump => Plugin.JumpCancelCost.Value, 
				DefensiveCancel.Sprint => Plugin.SprintCancelCost.Value, 
				_ => Plugin.BlockCancelCost.Value, 
			};
			if (orCreateValue.Secondary)
			{
				num += Plugin.SecondaryExtraCost.Value;
			}
			switch (cancel)
			{
			case DefensiveCancel.Dodge:
			{
				float normalDodgeCost = GetNormalDodgeCost(player);
				if (!((Character)player).HaveStamina(normalDodgeCost + num + 0.01f))
				{
					return;
				}
				break;
			}
			case DefensiveCancel.Jump:
				if (!((Character)player).HaveStamina(((Character)player).m_jumpStaminaUsage + num + 0.01f))
				{
					return;
				}
				break;
			default:
				if (!((Character)player).HaveStamina(num + 0.01f))
				{
					return;
				}
				break;
			}
			if (num > 0f)
			{
				((Character)player).UseStamina(num);
			}
			val.Stop();
			QueuedAttackTimer.Invoke(player) = 0f;
			QueuedSecondAttackTimer.Invoke(player) = 0f;
			orCreateValue.SuppressAttack = true;
			orCreateValue.CancelledAttack = val;
			orCreateValue.SuppressUntil = Time.time + Plugin.CancelBlendTime.Value + 0.03f;
			orCreateValue.SprintCancelledAt = ((cancel == DefensiveCancel.Sprint) ? Time.time : (-100f));
			orCreateValue.Cancel = cancel;
			FlowEnhancements.OnCancelled(player, cancel);
		}

		private static float GetNormalDodgeCost(Player player)
		{
			if (GetDodgeStaminaUseMethod == null)
			{
				return player.m_dodgeStaminaUsage;
			}
			object obj = GetDodgeStaminaUseMethod.Invoke(player, null);
			if (!(obj is float))
			{
				return player.m_dodgeStaminaUsage;
			}
			return (float)obj;
		}

		internal static void OverrideInAttack(Player player, ref bool result)
		{
			if (IsLocal(player) && States.TryGetValue(player, out var value) && value.SuppressAttack)
			{
				if (!result && Time.time >= value.SuppressUntil)
				{
					value.SuppressAttack = false;
					value.Cancel = DefensiveCancel.None;
				}
				else
				{
					result = false;
				}
			}
		}

		internal static bool ShouldRejectNewAttack(Player player)
		{
			if (!IsLocal(player))
			{
				return false;
			}
			if (States.TryGetValue(player, out var value))
			{
				return value.SuppressAttack;
			}
			return false;
		}

		internal static void Reset()
		{
			States = new ConditionalWeakTable<Player, State>();
			FlowEnhancements.Reset();
		}
	}
	[HarmonyPatch(typeof(Humanoid), "StartAttack")]
	internal static class StartAttackPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(Humanoid __instance, ref bool __result)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val != (Object)null && CombatFlow.ShouldRejectNewAttack(val))
			{
				__result = false;
				return false;
			}
			return true;
		}

		[HarmonyPostfix]
		private static void Postfix(Humanoid __instance, bool __result)
		{
			if (__result)
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if ((Object)(object)val != (Object)null)
				{
					CombatFlow.AttackStarted(val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "OnAttackTrigger")]
	internal static class AttackTriggerPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(Humanoid __instance)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (!((Object)(object)val == (Object)null))
			{
				return !CombatFlow.BlocksAttackTrigger(val);
			}
			return true;
		}

		[HarmonyPostfix]
		private static void Postfix(Humanoid __instance)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val != (Object)null && !CombatFlow.BlocksAttackTrigger(val))
			{
				CombatFlow.AttackTriggered(val);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateDodge")]
	internal static class UpdateDodgePatch
	{
		[HarmonyPrefix]
		private static void Prefix(Player __instance)
		{
			CombatFlow.BeforeDodge(__instance);
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UpdateBlock")]
	internal static class UpdateBlockPatch
	{
		[HarmonyPrefix]
		private static void Prefix(Humanoid __instance)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val != (Object)null)
			{
				CombatFlow.BeforeBlock(val);
			}
		}
	}
	[HarmonyPatch(typeof(Character), "Jump")]
	internal static class JumpCancelPatch
	{
		[HarmonyPrefix]
		private static void Prefix(Character __instance, bool force)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val != (Object)null)
			{
				CombatFlow.BeforeJump(val, force);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "InAttack")]
	internal static class PlayerInAttackPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Player __instance, ref bool __result)
		{
			CombatFlow.OverrideInAttack(__instance, ref __result);
		}
	}
}