Decompiled source of ComboSpear v1.0.2

BepInEx/plugins/ComboSpear.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ComboSpear")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ComboSpear")]
[assembly: AssemblyTitle("ComboSpear")]
[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 SpearCombo
{
	[BepInPlugin("andythedemon.combospear", "Combo Spear", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		internal readonly struct Setting<T>
		{
			private readonly T value;

			internal T Value => value;

			internal Setting(T v)
			{
				value = v;
			}
		}

		public const string Guid = "andythedemon.combospear";

		public const string PluginName = "Combo Spear";

		public const string Version = "1.0.1";

		internal const string ComboTrigger = "spearcombo";

		internal const string VanillaPoke = "spear_poke";

		internal const string ThrowTrigger = "spear_throw";

		internal const string GuardTrigger = "spearguard";

		internal const string IgnoredTrigger = "spear_dup_ignored";

		internal const float LungeHitSeconds = 0.667f;

		internal const float ThrowWindowSeconds = 1.6f;

		internal const string KnifeLunge = "knife-lunge";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static readonly Setting<float> NormalHitDamage = new Setting<float>(1f);

		internal static readonly Setting<float> BlockHitDamage = new Setting<float>(1f);

		internal static readonly Setting<float> ThrowDamage = new Setting<float>(0.5f);

		internal static readonly Setting<string>[] Hit = new Setting<string>[3]
		{
			new Setting<string>("knife_stab0"),
			new Setting<string>("knife_stab1"),
			new Setting<string>("knife_stab2")
		};

		internal static readonly Setting<float>[] HitSpeed = new Setting<float>[3]
		{
			new Setting<float>(1f),
			new Setting<float>(1f),
			new Setting<float>(1f)
		};

		internal static readonly Setting<Vector3>[] HitRotation = new Setting<Vector3>[3]
		{
			new Setting<Vector3>(Vector3.zero),
			new Setting<Vector3>(Vector3.zero),
			new Setting<Vector3>(Vector3.zero)
		};

		internal static readonly Setting<Vector3>[] HitOffset = new Setting<Vector3>[3]
		{
			new Setting<Vector3>(Vector3.zero),
			new Setting<Vector3>(Vector3.zero),
			new Setting<Vector3>(Vector3.zero)
		};

		internal static readonly Setting<float> LastHitDamage = new Setting<float>(2f);

		internal static readonly Setting<float> Range = new Setting<float>(3.2f);

		internal static readonly Setting<Vector3> ComboGrip = new Setting<Vector3>(new Vector3(-8f, 23f, 12f));

		internal static readonly Setting<float> ComboGripBlend = new Setting<float>(0.12f);

		internal static readonly Setting<float> ComboGripOut = new Setting<float>(0.25f);

		internal static readonly Setting<bool> JumpBackThrow = new Setting<bool>(v: true);

		internal static readonly Setting<bool> KeepBlockPose = new Setting<bool>(v: false);

		internal static readonly Setting<bool> DefenceCombo = new Setting<bool>(v: true);

		internal static readonly Setting<float> GuardReset = new Setting<float>(1f);

		internal static readonly Setting<float> GuardHold = new Setting<float>(0f);

		internal static readonly Setting<string>[] GuardClip = new Setting<string>[3]
		{
			new Setting<string>("SpearGuard1"),
			new Setting<string>("SpearGuard2"),
			new Setting<string>("SpearGuard3")
		};

		internal static readonly Setting<float>[] GuardDamage = new Setting<float>[3]
		{
			new Setting<float>(0.5f),
			new Setting<float>(0.7f),
			new Setting<float>(1f)
		};

		internal static readonly Setting<float> JumpBackHeight = new Setting<float>(1f);

		internal static readonly Setting<float> JumpBackDistance = new Setting<float>(2f);

		internal static readonly Setting<float> JumpBackDelay = new Setting<float>(0.2f);

		internal static readonly Setting<string> ThrowCustomClip = new Setting<string>("SpearThrowBack");

		internal static readonly Setting<string> ThrowCustomClipFree = new Setting<string>("SpearThrowBack_Free");

		internal static readonly Setting<string> ThrowReplacesClip = new Setting<string>("throw_spear");

		internal static readonly Setting<string> PlainThrowClip = new Setting<string>("SpearThrowPlain");

		internal static readonly Setting<bool> Flip = new Setting<bool>(v: true);

		internal static readonly Setting<bool> Dump = new Setting<bool>(v: false);

		internal static readonly Setting<string> CustomBundle = new Setting<string>("spearcombo.bundle");

		internal static readonly Setting<bool> TrueDamageNumbers = new Setting<bool>(v: true);

		internal static readonly Setting<string>[] HitCustomClip = new Setting<string>[3]
		{
			new Setting<string>("SpearJab1"),
			new Setting<string>("SpearJab2"),
			new Setting<string>("SpearLunge")
		};

		internal static readonly Setting<string>[] HitCustomClipFree = new Setting<string>[3]
		{
			new Setting<string>("SpearJab1_Free"),
			new Setting<string>("SpearJab2_Free"),
			new Setting<string>("SpearLunge_Free")
		};

		internal static readonly Setting<string>[] HitReplaceClip = new Setting<string>[3]
		{
			new Setting<string>("knife_slash0"),
			new Setting<string>("knife_slash1"),
			new Setting<string>("knife_slash2")
		};

		internal static string PluginFolder;

		private bool dumped;

		private void Awake()
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_046f: Expected O, but got Unknown
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Expected O, but got Unknown
			//IL_02fe: Expected O, but got Unknown
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Expected O, but got Unknown
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e8: Expected O, but got Unknown
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Expected O, but got Unknown
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			//IL_01c8: Expected O, but got Unknown
			//IL_0563: Unknown result type (might be due to invalid IL or missing references)
			//IL_0580: Unknown result type (might be due to invalid IL or missing references)
			//IL_058b: Expected O, but got Unknown
			//IL_058b: Expected O, but got Unknown
			//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cd: Expected O, but got Unknown
			//IL_05cd: Expected O, but got Unknown
			//IL_05e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f5: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Turns Combo Spear on or off. Off: spears attack, block and throw exactly as in vanilla. Takes effect the next time the game starts.");
			if (!Enabled.Value)
			{
				Log.LogInfo((object)"Combo Spear 1.0.1 is turned off in its config (General / Enabled) - nothing is changed.");
				return;
			}
			Log.LogInfo((object)$"Damage: normal hits x{NormalHitDamage.Value:0.##}, block hits x{BlockHitDamage.Value:0.##}, jump-back throw x{ThrowDamage.Value:0.##}.");
			PluginFolder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			Refs.Init();
			if (Chainloader.PluginInfos.ContainsKey("goldenrevolver.ProperSpears"))
			{
				Log.LogWarning((object)"Proper Spears is installed too - both change spears; disable one of them.");
			}
			Harmony val = new Harmony("andythedemon.combospear");
			val.PatchAll(typeof(Plugin).Assembly);
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Humanoid), "StartAttack", new Type[2]
				{
					typeof(Character),
					typeof(bool)
				}, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(Player), "InAttack", (Type[])null, (Type[])null);
				if (methodInfo != null && methodInfo2 != null && Refs.CurrentAttack != null && Refs.Zanim != null)
				{
					val.Patch((MethodBase)methodInfo2, new HarmonyMethod(AccessTools.Method(typeof(LungeCancel), "InAttackPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					val.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(LungeCancel), "Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(LungeCancel), "Finalizer", (Type[])null, (Type[])null)), (HarmonyMethod)null);
				}
				else
				{
					Log.LogError((object)"StartAttack / Player.InAttack / m_currentAttack / m_zanim not found; cancelling the lunge is off.");
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Could not patch the lunge cancel (" + ex.GetType().Name + "); cancelling the lunge is off."));
			}
			try
			{
				MethodInfo methodInfo3 = AccessTools.Method(typeof(Character), "ApplyDamage", new Type[4]
				{
					typeof(HitData),
					typeof(bool),
					typeof(bool),
					typeof(DamageModifier)
				}, (Type[])null);
				MethodInfo methodInfo4 = AccessTools.Method(typeof(DamageText), "ShowText", new Type[4]
				{
					typeof(DamageModifier),
					typeof(Vector3),
					typeof(float),
					typeof(bool)
				}, (Type[])null);
				if (methodInfo3 != null && methodInfo4 != null)
				{
					val.Patch((MethodBase)methodInfo3, new HarmonyMethod(AccessTools.Method(typeof(TrueDamage), "ApplyPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(TrueDamage), "ApplyFinalizer", (Type[])null, (Type[])null)), (HarmonyMethod)null);
					val.Patch((MethodBase)methodInfo4, new HarmonyMethod(AccessTools.Method(typeof(TrueDamage), "ShowTextPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)"True damage numbers: on (shows the damage a hit really deals).");
				}
				else
				{
					Log.LogError((object)"Character.ApplyDamage / DamageText.ShowText not found; damage numbers are left as they are.");
				}
			}
			catch (Exception ex2)
			{
				Log.LogError((object)("Could not patch the damage numbers (" + ex2.GetType().Name + "); they are left as they are."));
			}
			try
			{
				MethodInfo methodInfo5 = AccessTools.Method(typeof(Humanoid), "StartAttack", new Type[2]
				{
					typeof(Character),
					typeof(bool)
				}, (Type[])null);
				if (methodInfo5 != null && Refs.CurrentAttack != null)
				{
					val.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(SoftThrow), "Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else
				{
					Log.LogError((object)"Humanoid.StartAttack / m_currentAttack not found; the jump-back throw hits at full damage.");
				}
			}
			catch (Exception ex3)
			{
				Log.LogError((object)("Could not patch the jump-back throw damage (" + ex3.GetType().Name + "); it hits at full damage."));
			}
			try
			{
				MethodInfo methodInfo6 = AccessTools.Method(typeof(Attack), "FireProjectileBurst", (Type[])null, (Type[])null);
				if (methodInfo6 != null)
				{
					val.Patch((MethodBase)methodInfo6, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(GameThrowWatch), "BurstPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception ex4)
			{
				Log.LogError((object)("Could not watch projectile bursts (" + ex4.GetType().Name + "); the throw fallback may double-fire."));
			}
			try
			{
				MethodInfo methodInfo7 = AccessTools.Method(typeof(Humanoid), "StartAttack", new Type[2]
				{
					typeof(Character),
					typeof(bool)
				}, (Type[])null);
				MethodInfo methodInfo8 = AccessTools.Method(typeof(Character), "RPC_Damage", (Type[])null, (Type[])null);
				MethodInfo methodInfo9 = AccessTools.Method(typeof(Humanoid), "IsBlocking", (Type[])null, (Type[])null);
				if (methodInfo7 != null && methodInfo8 != null && methodInfo9 != null && Refs.Blocking != null && Refs.CurrentAttack != null)
				{
					val.Patch((MethodBase)methodInfo7, new HarmonyMethod(AccessTools.Method(typeof(GuardCombo), "Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(GuardCombo), "Finalizer", (Type[])null, (Type[])null)), (HarmonyMethod)null);
					val.Patch((MethodBase)methodInfo8, new HarmonyMethod(AccessTools.Method(typeof(GuardCombo), "DamagePrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(GuardCombo), "DamageFinalizer", (Type[])null, (Type[])null)), (HarmonyMethod)null);
					val.Patch((MethodBase)methodInfo9, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(GuardCombo), "IsBlockingPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else
				{
					Log.LogError((object)"StartAttack / RPC_Damage / IsBlocking / m_blocking not found; the defence combo is off.");
				}
			}
			catch (Exception ex5)
			{
				Log.LogError((object)("Could not patch the defence combo (" + ex5.GetType().Name + "); it is off."));
			}
			Log.LogInfo((object)"Combo Spear 1.0.1 loaded.");
		}

		private void Update()
		{
			if (Enabled == null || !Enabled.Value)
			{
				return;
			}
			WiresShim.Ensure();
			if (dumped || !Dump.Value || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			dumped = true;
			try
			{
				AnimationDump.Write(Player.m_localPlayer);
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Animation dump failed: " + ex));
			}
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public Action<ConfigEntryBase> CustomDrawer;

		public int? Order;
	}
	internal static class Refs
	{
		internal static FieldRef<Attack, int> ChainLevels;

		internal static FieldRef<Attack, float> LastChainDamage;

		internal static FieldRef<Attack, int> ChainLevel;

		internal static FieldRef<ZSyncAnimation, Animator> AnimatorOf;

		internal static FieldRef<VisEquipment, GameObject> RightItem;

		internal static FieldRef<VisEquipment, int> LeftItemHash;

		internal static FieldRef<VisEquipment, int> RightItemHash;

		internal static FieldInfo SecondaryAttack;

		internal static FieldInfo CurrentAttack;

		internal static FieldInfo Zanim;

		internal static FieldInfo Blocking;

		internal static FieldRef<Humanoid, bool> InternalBlocking;

		internal static FieldRef<Player, float> QueuedAttack;

		internal static FieldRef<Humanoid, float> TimeSinceLastAttack;

		internal static FieldInfo BlockingAnimHash;

		internal static MethodInfo FireProjectileBurst;

		internal static Transform CharacterRoot(Transform t)
		{
			Character componentInParent = ((Component)t).GetComponentInParent<Character>();
			if (!((Object)(object)componentInParent != (Object)null))
			{
				return t.root;
			}
			return ((Component)componentInParent).transform;
		}

		internal static void Init()
		{
			ChainLevels = Get<Attack, int>("m_attackChainLevels");
			LastChainDamage = Get<Attack, float>("m_lastChainDamageMultiplier");
			ChainLevel = Get<Attack, int>("m_currentAttackCainLevel");
			AnimatorOf = Get<ZSyncAnimation, Animator>("m_animator");
			RightItem = Get<VisEquipment, GameObject>("m_rightItemInstance");
			LeftItemHash = Get<VisEquipment, int>("m_currentLeftItemHash");
			RightItemHash = Get<VisEquipment, int>("m_currentRightItemHash");
			SecondaryAttack = AccessTools.Field(typeof(SharedData), "m_secondaryAttack");
			CurrentAttack = AccessTools.Field(typeof(Humanoid), "m_currentAttack");
			Zanim = AccessTools.Field(typeof(Character), "m_zanim");
			Blocking = AccessTools.Field(typeof(Character), "m_blocking");
			InternalBlocking = Get<Humanoid, bool>("m_internalBlockingState");
			QueuedAttack = Get<Player, float>("m_queuedAttackTimer");
			TimeSinceLastAttack = Get<Humanoid, float>("m_timeSinceLastAttack");
			BlockingAnimHash = AccessTools.Field(typeof(Humanoid), "s_blocking");
			FireProjectileBurst = AccessTools.Method(typeof(Attack), "FireProjectileBurst", (Type[])null, (Type[])null);
			if (CurrentAttack == null || Zanim == null)
			{
				Plugin.Log.LogError((object)"m_currentAttack / m_zanim not found; cancelling the lunge is off.");
			}
		}

		private static FieldRef<T, F> Get<T, F>(string field) where T : class
		{
			try
			{
				return AccessTools.FieldRefAccess<T, F>(field);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Field " + typeof(T).Name + "." + field + " not found (" + ex.GetType().Name + "); that feature is off."));
				return null;
			}
		}

		internal static int Levels(Attack a)
		{
			if (ChainLevels == null)
			{
				return 1;
			}
			return ChainLevels.Invoke(a);
		}
	}
	internal static class Combo
	{
		private static string resolvedLunge;

		internal static bool IsComboSpear(SharedData s)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (s != null && (int)s.m_skillType == 5 && s.m_attack != null)
			{
				if (!(s.m_attack.m_attackAnimation == "spear_poke"))
				{
					return s.m_attack.m_attackAnimation == "spearcombo";
				}
				return true;
			}
			return false;
		}

		internal static SharedData SharedOf(GameObject go)
		{
			ItemDrop val = (Object.op_Implicit((Object)(object)go) ? go.GetComponent<ItemDrop>() : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.m_itemData?.m_shared;
		}

		internal static SharedData SharedFromHash(int hash)
		{
			if (hash != 0 && !((Object)(object)ObjectDB.instance == (Object)null))
			{
				return SharedOf(ObjectDB.instance.GetItemPrefab(hash));
			}
			return null;
		}

		internal static void Apply(SharedData s)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			if (s == null || (int)s.m_skillType != 5 || s.m_attack == null)
			{
				return;
			}
			Attack attack = s.m_attack;
			if (attack.m_attackAnimation != "spear_poke" || Refs.ChainLevels == null)
			{
				return;
			}
			attack.m_attackAnimation = "spearcombo";
			Refs.ChainLevels.Invoke(attack) = 3;
			DestructibleType resetChainIfHit = attack.m_resetChainIfHit;
			attack.m_resetChainIfHit = (DestructibleType)0;
			if (Refs.LastChainDamage != null)
			{
				Refs.LastChainDamage.Invoke(attack) = Plugin.LastHitDamage.Value;
			}
			attack.m_attackRange = Plugin.Range.Value;
			attack.m_attackHeight = 1f;
			attack.m_attackAngle = 30f;
			attack.m_attackRayWidth = 0.4f;
			if (Plugin.JumpBackThrow.Value)
			{
				object? obj = Refs.SecondaryAttack?.GetValue(s);
				Attack val = (Attack)((obj is Attack) ? obj : null);
				if (val != null)
				{
					val.m_damageMultiplier = 1f;
				}
			}
			Plugin.Log.LogInfo((object)$"Combo applied to {s.m_name} (chain reset-if-hit {resetChainIfHit} -> None).");
		}

		internal static string MapTrigger(string name, out int level)
		{
			return MapTrigger(name, "spearcombo", out level);
		}

		internal static string MapTrigger(string name, string prefix, out int level)
		{
			level = 0;
			if (name.Length > prefix.Length)
			{
				int.TryParse(name.Substring(prefix.Length), out level);
			}
			level = Mathf.Clamp(level, 0, 2);
			return Resolve(Plugin.Hit[level].Value);
		}

		internal static string Resolve(string configured)
		{
			if (!(configured == "knife-lunge"))
			{
				return configured;
			}
			return LungeTrigger();
		}

		private static string LungeTrigger()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			if (resolvedLunge != null)
			{
				return resolvedLunge;
			}
			if ((Object)(object)ObjectDB.instance != (Object)null && Refs.ChainLevels != null)
			{
				foreach (GameObject item in ObjectDB.instance.m_items)
				{
					SharedData val = SharedOf(item);
					if (val != null && (int)val.m_skillType == 2 && val.m_attack != null)
					{
						int num = Refs.Levels(val.m_attack);
						if (num >= 3 && !string.IsNullOrEmpty(val.m_attack.m_attackAnimation))
						{
							resolvedLunge = val.m_attack.m_attackAnimation + (num - 1);
							Plugin.Log.LogInfo((object)("knife-lunge = '" + resolvedLunge + "' (from " + ((Object)item).name + ")."));
							return resolvedLunge;
						}
					}
				}
			}
			resolvedLunge = "knife_stab2";
			Plugin.Log.LogWarning((object)("Could not read the knife combo; guessing '" + resolvedLunge + "'. Pick the lunge from the list if it does nothing."));
			return resolvedLunge;
		}
	}
	internal class AnimOption
	{
		public string Trigger;

		public string Label;
	}
	internal static class AnimationCatalog
	{
		private static readonly HashSet<string> PlayerItemTypes = new HashSet<string> { "OneHandedWeapon", "TwoHandedWeapon", "TwoHandedWeaponLeft", "Bow", "Torch", "Tool" };

		private static List<AnimOption> cache;

		internal static List<AnimOption> Get()
		{
			if (cache != null)
			{
				return cache;
			}
			if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null || ObjectDB.instance.m_recipes.Count == 0)
			{
				return null;
			}
			HashSet<SharedData> hashSet = new HashSet<SharedData>();
			foreach (Recipe recipe in ObjectDB.instance.m_recipes)
			{
				SharedData val = ((!((Object)(object)recipe != (Object)null) || !((Object)(object)recipe.m_item != (Object)null)) ? null : recipe.m_item.m_itemData?.m_shared);
				if (val != null)
				{
					hashSet.Add(val);
				}
			}
			HashSet<string> seen = new HashSet<string> { "knife-lunge" };
			List<AnimOption> list = new List<AnimOption>();
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				SharedData val2 = Combo.SharedOf(item);
				if (val2 != null && hashSet.Contains(val2) && PlayerItemTypes.Contains(((object)Unsafe.As<ItemType, ItemType>(ref val2.m_itemType)/*cast due to .constrained prefix*/).ToString()))
				{
					string weapon = Localize(val2.m_name);
					AddAttack(list, seen, weapon, "primary", val2.m_attack);
					object? obj = Refs.SecondaryAttack?.GetValue(val2);
					AddAttack(list, seen, weapon, "secondary", (Attack)((obj is Attack) ? obj : null));
				}
			}
			list.Sort((AnimOption a, AnimOption b) => string.CompareOrdinal(a.Label, b.Label));
			List<AnimOption> list2 = new List<AnimOption>();
			list2.Add(new AnimOption
			{
				Trigger = "knife-lunge",
				Label = "knife-lunge   (knife combo finisher, auto-detected)"
			});
			list2.AddRange(list);
			cache = list2;
			return cache;
		}

		private static string Localize(string token)
		{
			try
			{
				return (Localization.instance != null) ? Localization.instance.Localize(token) : token;
			}
			catch
			{
				return token;
			}
		}

		private static void AddAttack(List<AnimOption> list, HashSet<string> seen, string weapon, string kind, Attack a)
		{
			if (a == null || string.IsNullOrEmpty(a.m_attackAnimation))
			{
				return;
			}
			bool num = a.m_attackAnimation == "spearcombo";
			string text = (num ? "spear_poke" : a.m_attackAnimation);
			int num2 = (num ? 1 : Refs.Levels(a));
			if (num2 <= 1)
			{
				if (seen.Add(text))
				{
					list.Add(new AnimOption
					{
						Trigger = text,
						Label = text + "   (" + weapon + ", " + kind + ")"
					});
				}
				return;
			}
			for (int i = 0; i < num2; i++)
			{
				string text2 = text + i;
				if (seen.Add(text2))
				{
					list.Add(new AnimOption
					{
						Trigger = text2,
						Label = $"{text2}   ({weapon}, {kind} hit {i + 1}/{num2})"
					});
				}
			}
		}
	}
	internal static class AnimPicker
	{
		private static readonly Dictionary<ConfigEntryBase, bool> open = new Dictionary<ConfigEntryBase, bool>();

		private static readonly Dictionary<ConfigEntryBase, Vector2> scroll = new Dictionary<ConfigEntryBase, Vector2>();

		internal static void Draw(ConfigEntryBase entryBase)
		{
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<string> val = (ConfigEntry<string>)(object)entryBase;
			List<AnimOption> list = AnimationCatalog.Get();
			open.TryGetValue((ConfigEntryBase)(object)val, out var value);
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("<", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }) && list != null)
			{
				Step(val, list, -1);
			}
			string text = GUILayout.TextField(val.Value, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if (text != val.Value)
			{
				val.Value = text;
			}
			if (GUILayout.Button(">", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }) && list != null)
			{
				Step(val, list, 1);
			}
			if (GUILayout.Button(value ? "Close" : "List", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) }))
			{
				value = (open[(ConfigEntryBase)(object)val] = !value);
			}
			GUILayout.EndHorizontal();
			if (value)
			{
				if (list == null)
				{
					GUILayout.Label("Enter a world first - the list is read from the game.", Array.Empty<GUILayoutOption>());
				}
				else
				{
					scroll.TryGetValue((ConfigEntryBase)(object)val, out var value2);
					scroll[(ConfigEntryBase)(object)val] = GUILayout.BeginScrollView(value2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(260f) });
					foreach (AnimOption item in list)
					{
						if (GUILayout.Button((item.Trigger == val.Value) ? ("> " + item.Label) : item.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
						{
							val.Value = item.Trigger;
							open[(ConfigEntryBase)(object)val] = false;
						}
					}
					GUILayout.EndScrollView();
				}
			}
			GUILayout.EndVertical();
		}

		private static void Step(ConfigEntry<string> entry, List<AnimOption> options, int dir)
		{
			int num = options.FindIndex((AnimOption o) => o.Trigger == entry.Value);
			num = ((num >= 0) ? ((num + dir + options.Count) % options.Count) : 0);
			entry.Value = options[num].Trigger;
		}
	}
	internal static class AnimationDump
	{
		internal static void Write(Player player)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("Valheim attack animations (written by Spear Combo). Use these names for Hit1..Hit3.");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("== Attacks of player weapons (craftable) ==");
			List<AnimOption> list = AnimationCatalog.Get();
			if (list != null)
			{
				foreach (AnimOption item in list)
				{
					stringBuilder.AppendLine(item.Label);
				}
			}
			Animator val = ((Refs.AnimatorOf != null) ? Refs.AnimatorOf.Invoke(((Component)player).GetComponent<ZSyncAnimation>()) : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.runtimeAnimatorController != (Object)null)
			{
				stringBuilder.AppendLine();
				stringBuilder.AppendLine("== Animation clips in the player controller (for custom-clip replacement later) ==");
				SortedSet<string> sortedSet = new SortedSet<string>(StringComparer.Ordinal);
				AnimationClip[] animationClips = val.runtimeAnimatorController.animationClips;
				foreach (AnimationClip val2 in animationClips)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						sortedSet.Add($"{((Object)val2).name}  ({val2.length:0.00}s)");
					}
				}
				foreach (string item2 in sortedSet)
				{
					stringBuilder.AppendLine(item2);
				}
			}
			string text = Path.Combine(Paths.BepInExRootPath, "SpearCombo-animations.txt");
			File.WriteAllText(text, stringBuilder.ToString());
			Plugin.Log.LogInfo((object)("Animation list written to " + text));
		}
	}
	internal class FlipMark : MonoBehaviour
	{
		public bool Flipped;

		public bool Fang;

		public bool PoseActive;

		public float ReflipAt;

		public float GripW;

		public float RegripW;

		public bool RegripToss;

		public float LastTossLog;

		public bool AimLock;

		public float LastAimLog;

		public bool RegripJump;

		public bool TossCaptured;

		public Quaternion TossRot;

		public Vector3 TossPos;

		public bool TossHoldLogged;

		public int Level = -1;

		private ComboState state;

		private Humanoid owner;

		private void LateUpdate()
		{
			if (!Flipped)
			{
				GripW = 0f;
				return;
			}
			if ((Object)(object)state == (Object)null)
			{
				state = ((Component)this).GetComponentInParent<ComboState>();
			}
			RegripW = (((Object)(object)state != (Object)null && state.ThrowAt > 0f) ? SpearFlip.Regrip(Time.time - state.ThrowAt) : 0f);
			RegripToss = RegripW > 0f;
			RegripJump = RegripW > 0f;
			LastTossLog = Time.time;
			AimLock = (Object)(object)state != (Object)null && ((state.PlainThrowAt > 0f && Time.time - state.PlainThrowAt < 0.95f) || (state.ThrowAt > 0f && Time.time - state.ThrowAt < 1.15f));
			if (RegripW <= 0f && (Object)(object)state != (Object)null && state.PlainThrowAt > 0f)
			{
				RegripW = SpearFlip.PlainRegrip(Time.time - state.PlainThrowAt);
				RegripToss = RegripW > 0f;
				RegripJump = false;
			}
			if ((Object)(object)owner == (Object)null)
			{
				owner = ((Component)this).GetComponentInParent<Humanoid>();
			}
			bool flag = (Object)(object)state != (Object)null && state.Guard && Time.time <= state.LastActive + Plugin.GuardReset.Value && SpearFlip.BlockHeld(owner);
			float num = (((Object)(object)state != (Object)null && ((!state.Exiting && (state.Level >= 0 || Time.time < state.LastActive + 0.15f)) || flag)) ? 1f : 0f);
			if (GripW != num || GripW != 0f || !(RegripW <= 0f))
			{
				float num2 = Time.deltaTime / Mathf.Max(0.01f, (num > GripW) ? Plugin.ComboGripBlend.Value : Plugin.ComboGripOut.Value);
				GripW = Mathf.MoveTowards(GripW, num, num2);
				SpearFlip.ApplyPose(((Component)this).gameObject, this, ((Object)(object)state != (Object)null) ? state.Level : (-1));
			}
		}
	}
	internal static class SpearFlip
	{
		private static readonly Vector3 PalmOffset = new Vector3(-0.016f, 0.0185f, 0.0002f);

		private const float TossStart = 0.2f;

		private const float TossEnd = 0.713f;

		private const float TossLift = 0.26f;

		private const float TossLandFrom = 0.4f;

		private const float TossPeak = 2.45f;

		private const float BodyClear = 0.34f;

		private const float SpearLength = 1.9f;

		private static readonly Vector3 TossShift = new Vector3(-0.06f, 0.06f, 0f);

		internal const float PlainTurnStart = 0.2f;

		internal const float PlainTurnEnd = 0.713f;

		internal static float JumpTossStart => 0.3f;

		internal static float JumpTossEnd => 0.8f;

		internal static bool BlockHeld(Humanoid h)
		{
			if ((Object)(object)h == (Object)null)
			{
				return false;
			}
			if ((Object)(object)h != (Object)(object)Player.m_localPlayer)
			{
				return ((Character)h).IsBlocking();
			}
			bool flag = default(bool);
			int num;
			if (Refs.Blocking != null)
			{
				object value = Refs.Blocking.GetValue(h);
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) == 0)
			{
				return GuardCombo.BlockButtonHeld();
			}
			return true;
		}

		internal static Quaternion RegripRot(Quaternion r1, float w)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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)
			Quaternion val = Quaternion.Inverse(r1);
			float num = default(float);
			Vector3 val2 = default(Vector3);
			((Quaternion)(ref val)).ToAngleAxis(ref num, ref val2);
			if (num > 180f)
			{
				num = 360f - num;
				val2 = -val2;
			}
			return r1 * Quaternion.AngleAxis((num - 360f) * w, val2);
		}

		internal static float PlainRegrip(float t)
		{
			if (t < 0f || t > 0.833f)
			{
				return 0f;
			}
			return Mathf.Clamp01((t - 0.2f) / 0.513f);
		}

		internal static float Regrip(float t)
		{
			if (t < 0f || t > JumpTossEnd + 0.12f)
			{
				return 0f;
			}
			return Mathf.Clamp01((t - 0.2f) / 0.513f);
		}

		internal static void Flip(GameObject go, bool fang)
		{
			FlipMark flipMark = go.GetComponent<FlipMark>() ?? go.AddComponent<FlipMark>();
			flipMark.Fang = fang;
			flipMark.Flipped = true;
			ApplyPose(go, flipMark, -1);
		}

		internal static void ApplyPose(GameObject go, FlipMark m, int hitLevel)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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_072a: Unknown result type (might be due to invalid IL or missing references)
			//IL_072f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0733: Unknown result type (might be due to invalid IL or missing references)
			//IL_0738: Unknown result type (might be due to invalid IL or missing references)
			//IL_073d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0742: Unknown result type (might be due to invalid IL or missing references)
			//IL_0744: Unknown result type (might be due to invalid IL or missing references)
			//IL_074a: Unknown result type (might be due to invalid IL or missing references)
			//IL_074f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: 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_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_08be: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a4: 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_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_07b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_07b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_07bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_07be: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_07cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0819: Unknown result type (might be due to invalid IL or missing references)
			//IL_0828: Unknown result type (might be due to invalid IL or missing references)
			//IL_0837: Unknown result type (might be due to invalid IL or missing references)
			//IL_0846: Unknown result type (might be due to invalid IL or missing references)
			//IL_0855: Unknown result type (might be due to invalid IL or missing references)
			//IL_0864: Unknown result type (might be due to invalid IL or missing references)
			//IL_087b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0887: Unknown result type (might be due to invalid IL or missing references)
			//IL_0893: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f8: 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_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_041d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: 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_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_0478: Unknown result type (might be due to invalid IL or missing references)
			//IL_047b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0480: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_048e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_049a: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: 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_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0504: Unknown result type (might be due to invalid IL or missing references)
			//IL_0506: Unknown result type (might be due to invalid IL or missing references)
			//IL_0508: Unknown result type (might be due to invalid IL or missing references)
			//IL_050d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0523: Unknown result type (might be due to invalid IL or missing references)
			//IL_0525: 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_0533: 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_053a: Unknown result type (might be due to invalid IL or missing references)
			//IL_060f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0614: Unknown result type (might be due to invalid IL or missing references)
			//IL_0619: Unknown result type (might be due to invalid IL or missing references)
			//IL_061e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0623: Unknown result type (might be due to invalid IL or missing references)
			//IL_0626: Unknown result type (might be due to invalid IL or missing references)
			//IL_0628: Unknown result type (might be due to invalid IL or missing references)
			//IL_062d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0632: Unknown result type (might be due to invalid IL or missing references)
			//IL_0637: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0578: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0584: Unknown result type (might be due to invalid IL or missing references)
			//IL_0588: Unknown result type (might be due to invalid IL or missing references)
			//IL_0595: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_0565: Unknown result type (might be due to invalid IL or missing references)
			//IL_0677: Unknown result type (might be due to invalid IL or missing references)
			//IL_0682: Unknown result type (might be due to invalid IL or missing references)
			//IL_0695: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_059a: Unknown result type (might be due to invalid IL or missing references)
			//IL_059e: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a3: 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_05b2: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = go.transform;
			transform.localRotation = Quaternion.identity;
			transform.localPosition = Vector3.zero;
			m.PoseActive = false;
			if (!m.Flipped)
			{
				return;
			}
			transform.Rotate(180f, 25f, 0f);
			transform.Translate(Vector3.forward * (m.Fang ? (-0.72f) : (-0.5f)) + PalmOffset, (Space)1);
			if (m.GripW > 0f)
			{
				float num = m.GripW * m.GripW * (3f - 2f * m.GripW);
				Quaternion val = Quaternion.Slerp(Quaternion.identity, Quaternion.Euler(Plugin.ComboGrip.Value), num);
				transform.localRotation = val * transform.localRotation;
				transform.localPosition = val * transform.localPosition;
				m.PoseActive = true;
			}
			if (m.RegripW <= 0f)
			{
				m.TossCaptured = false;
				m.TossHoldLogged = false;
			}
			if (m.RegripW > 0f)
			{
				if (m.RegripToss)
				{
					Transform val2 = Refs.CharacterRoot(transform);
					if (!m.TossCaptured)
					{
						m.TossRot = Quaternion.Inverse(val2.rotation) * transform.rotation;
						m.TossPos = val2.InverseTransformPoint(transform.position);
						m.TossCaptured = true;
					}
					float regripW = m.RegripW;
					UnderGrip(transform, out var rot, out var pos);
					Vector3 val3 = GroundForward(val2);
					Vector3 val4 = rot * Vector3.forward;
					Vector3 val5 = pos + val4 * Vector3.Dot(transform.parent.position - pos, val4);
					Vector3 val6 = val5 + Quaternion.FromToRotation(rot * Vector3.back, val3) * (pos - val5);
					Vector3 val7 = (m.RegripJump ? val6 : val2.TransformPoint(m.TossPos));
					Vector3 val8 = Vector3.Lerp(val7, pos, 0.5f);
					float num2 = Mathf.Max(0.26f, val2.position.y + 2.45f - val8.y) * Mathf.Sin(MathF.PI * regripW);
					Quaternion val9 = Quaternion.FromToRotation(rot * Vector3.back, val3) * rot;
					Quaternion val10 = val2.rotation * m.TossRot;
					Vector3 val11 = GroundForward(val2);
					Quaternion val12 = Quaternion.FromToRotation(val10 * Vector3.back, val11) * val10;
					float num3 = 1f;
					float num4 = Mathf.Clamp01((regripW - 0.9f) / 0.1f);
					num3 = num3 * num3 * (3f - 2f * num3);
					num4 = num4 * num4 * (3f - 2f * num4);
					transform.rotation = Quaternion.Slerp(Quaternion.Slerp(val10, val12, num3), val9, num4);
					Vector3 val13 = (m.RegripJump ? TossPathJump.Sample(regripW) : TossPath.Sample(regripW));
					Vector3 val14 = GroundForward(val2);
					Vector3 val15 = Vector3.Cross(Vector3.up, val14);
					transform.position = val7 + val15 * (0f - val13.x) + val14 * val13.z + Vector3.up * val13.y;
					float num5 = num4;
					Vector3 val16 = (m.RegripJump ? TossPathJump.Sample(1f) : TossPath.Sample(1f));
					Vector3 val17 = val7 + val15 * (0f - val16.x) + val14 * val16.z + Vector3.up * val16.y;
					float num6 = Mathf.Clamp01((regripW - 0.4f) / 0.6f);
					num6 = num6 * num6 * (3f - 2f * num6);
					transform.position += (val6 - val17) * num6;
					if (num5 > 0f)
					{
						transform.position = Vector3.Lerp(transform.position, val6, num5);
					}
					if (transform.position.y > val2.position.y + 0.55f && transform.position.y < val2.position.y + 1.85f)
					{
						Vector3 position = transform.position;
						Vector3 val18 = transform.rotation * Vector3.back;
						Vector3 val19 = position + val18 * 1.9f;
						Vector2 val20 = default(Vector2);
						((Vector2)(ref val20))..ctor(position.x, position.z);
						Vector2 val21 = new Vector2(val19.x, val19.z);
						Vector2 val22 = default(Vector2);
						((Vector2)(ref val22))..ctor(val2.position.x, val2.position.z);
						Vector2 val23 = val21 - val20;
						float num7 = ((((Vector2)(ref val23)).sqrMagnitude > 1E-06f) ? Mathf.Clamp01(Vector2.Dot(val22 - val20, val23) / ((Vector2)(ref val23)).sqrMagnitude) : 0f);
						Vector2 val24 = val20 + val23 * num7 - val22;
						float magnitude = ((Vector2)(ref val24)).magnitude;
						if (magnitude < 0.34f)
						{
							Vector3 val25;
							if (!(magnitude > 0.0001f))
							{
								val25 = val2.right * (0.34f - magnitude);
							}
							else
							{
								Vector3 val26 = new Vector3(val24.x, 0f, val24.y);
								val25 = ((Vector3)(ref val26)).normalized * (0.34f - magnitude);
							}
							Vector3 val27 = val25;
							transform.position += val27 * (1f - num5);
						}
					}
					if (Time.time - m.LastTossLog > 0.1f && regripW > 0.02f && (regripW < 0.98f || !m.TossHoldLogged))
					{
						m.LastTossLog = Time.time;
						if (regripW >= 0.98f)
						{
							m.TossHoldLogged = true;
						}
						Vector3 val28 = val2.InverseTransformDirection(transform.rotation * Vector3.back);
						Vector3 val29 = val2.InverseTransformDirection(val9 * Vector3.back);
						Plugin.Log.LogDebug((object)(string.Format("[toss] {0} w={1:0.00} lift={2:0.000} height={3:0.00}m tip(body: x right, y up, z fwd)={4:0.00},{5:0.00},{6:0.00} ", m.RegripJump ? "JUMP-table" : "plain-table", regripW, num2, transform.position.y - val2.position.y, val28.x, val28.y, val28.z) + $"held-grip tip={val29.x:0.00},{val29.y:0.00},{val29.z:0.00} item={((Object)go).name}"));
					}
				}
				m.PoseActive = true;
			}
			if (m.AimLock)
			{
				Vector3 val30 = GroundForward(Refs.CharacterRoot(transform));
				transform.rotation = Quaternion.FromToRotation(transform.rotation * Vector3.back, val30) * transform.rotation;
			}
			if ((m.AimLock || m.RegripW > 0f) && Time.time - m.LastAimLog > 0.05f)
			{
				m.LastAimLog = Time.time;
				Transform val31 = Refs.CharacterRoot(transform);
				Vector3 val32 = (((Object)(object)val31 != (Object)null) ? val31.forward : Vector3.zero);
				Vector3 val33 = GroundForward(val31);
				Vector3 val34 = transform.rotation * Vector3.back;
				Plugin.Log.LogDebug((object)(string.Format("[aim] aim={0} w={1:0.00} body={2} ", m.AimLock, m.RegripW, ((Object)(object)val31 != (Object)null) ? ((Object)val31).name : "null") + $"bfwd=({val32.x:0.00},{val32.y:0.00},{val32.z:0.00}) gfwd=({val33.x:0.00},{val33.y:0.00},{val33.z:0.00}) " + $"tip=({val34.x:0.00},{val34.y:0.00},{val34.z:0.00})"));
			}
			if (hitLevel >= 0)
			{
				transform.Rotate(Plugin.HitRotation[hitLevel].Value);
				transform.Translate(Plugin.HitOffset[hitLevel].Value);
				m.PoseActive = true;
			}
		}

		private static Vector3 GroundForward(Transform body)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[3]
			{
				Vector3.forward,
				Vector3.up,
				Vector3.right
			};
			foreach (Vector3 val in array)
			{
				Vector3 val2 = body.rotation * val;
				val2.y = 0f;
				if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f)
				{
					return ((Vector3)(ref val2)).normalized;
				}
			}
			return Vector3.forward;
		}

		internal static void UnderGrip(Transform spear, out Quaternion rot, out Vector3 pos)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_0013: 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_009d: 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)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: 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_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			rot = spear.rotation;
			pos = spear.position;
			Transform parent = spear.parent;
			Transform val = (((Object)(object)parent != (Object)null) ? parent.parent : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Transform val2 = val.Find("RightHandIndex1");
			Transform val3 = val.Find("RightHandMiddle1");
			Transform val4 = val.Find("RightHandRing1");
			Transform val5 = val.Find("RightHandPinky1");
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null) && !((Object)(object)val4 == (Object)null) && !((Object)(object)val5 == (Object)null))
			{
				Vector3 val6 = Vector3.Cross(val2.position - val5.position, val3.position - val.position);
				if (!(((Vector3)(ref val6)).sqrMagnitude < 1E-10f))
				{
					Vector3 val7 = ((val2.position + val3.position + val4.position + val5.position) / 4f + val.position) * 0.5f;
					Vector3 val8 = spear.rotation * Vector3.forward;
					Vector3 val9 = spear.position + val8 * Vector3.Dot(val7 - spear.position, val8);
					Quaternion val10 = Quaternion.AngleAxis(180f, ((Vector3)(ref val6)).normalized);
					rot = val10 * spear.rotation;
					pos = val9 + val10 * (spear.position - val9);
				}
			}
		}

		internal static GameObject RightItemOf(Component c)
		{
			Humanoid component = c.GetComponent<Humanoid>();
			VisEquipment val = (((Object)(object)component != (Object)null) ? component.GetVisEquipment() : null);
			if (!((Object)(object)val != (Object)null) || Refs.RightItem == null)
			{
				return null;
			}
			return Refs.RightItem.Invoke(val);
		}
	}
	internal class JumpBack : MonoBehaviour
	{
		private float fireAt = -1f;

		internal void Arm(float delay)
		{
			fireAt = Time.time + delay;
			((Behaviour)this).enabled = true;
		}

		private void Update()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			if (!(fireAt < 0f) && !(Time.time < fireAt))
			{
				fireAt = -1f;
				((Behaviour)this).enabled = false;
				Character component = ((Component)this).GetComponent<Character>();
				if (!((Object)(object)component == (Object)null) && !component.IsDead() && component.IsOnGround())
				{
					float num = Mathf.Max(0.1f, 0f - Physics.gravity.y);
					float num2 = Mathf.Sqrt(2f * num * Mathf.Max(0f, Plugin.JumpBackHeight.Value));
					float num3 = 2f * num2 / num;
					float num4 = ((num3 > 0.01f) ? (Plugin.JumpBackDistance.Value / num3) : 0f);
					Vector3 val = -((Component)component).transform.forward;
					val.y = 0f;
					((Vector3)(ref val)).Normalize();
					component.ForceJump(val * num4 + Vector3.up * num2, false);
				}
			}
		}
	}
	internal static class GuardCombo
	{
		internal static bool SwallowedSinceStart;

		internal static float ArmedGuardAt = -10f;

		internal static int AttackStateHash;

		internal static int BlockStateHash;

		internal static float lastProbe;

		internal static int CallCount;

		internal static float LastCallAt;

		private static float pendingGap;

		private static bool pendingContinuing;

		private static float guardStartedAt = -10f;

		private static float lastTraceAt = -10f;

		private static Character damaged;

		private static bool blockWasHeld;

		private static readonly int ShieldBlockingState = Animator.StringToHash("Shield blocking");

		private static void Trace(string text)
		{
			if (!(Time.time - lastTraceAt < 0.25f))
			{
				lastTraceAt = Time.time;
				Plugin.Log.LogDebug((object)("[guard] " + text));
			}
		}

		internal static bool BlockButtonHeld()
		{
			try
			{
				if (Hud.InRadial())
				{
					return false;
				}
				return ZInput.GetButton("Block") || ZInput.GetButton("JoyBlock");
			}
			catch
			{
				return false;
			}
		}

		internal static bool Prefix(Humanoid __instance, bool secondaryAttack, out bool __state, ref bool __result)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			__state = false;
			if (secondaryAttack || !Plugin.DefenceCombo.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || Refs.Blocking == null)
			{
				return true;
			}
			object value = Refs.Blocking.GetValue(__instance);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			bool flag2 = (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			bool flag3 = BlockButtonHeld();
			bool flag4 = flag2 || flag3;
			if (flag4)
			{
				ArmedGuardAt = Time.time;
			}
			if (flag4 && Refs.Zanim != null)
			{
				object? value2 = Refs.Zanim.GetValue(__instance);
				ZSyncAnimation val = (ZSyncAnimation)((value2 is ZSyncAnimation) ? value2 : null);
				if (val != null)
				{
					Animator component = ((Component)val).GetComponent<Animator>();
					if ((Object)(object)component != (Object)null)
					{
						AnimatorStateInfo currentAnimatorStateInfo = component.GetCurrentAnimatorStateInfo(0);
						BlockStateHash = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).shortNameHash;
					}
				}
			}
			if (flag4 && Refs.Zanim != null)
			{
				object? value3 = Refs.Zanim.GetValue(__instance);
				ZSyncAnimation val2 = (ZSyncAnimation)((value3 is ZSyncAnimation) ? value3 : null);
				if (val2 != null)
				{
					ClearBlockPose(__instance, val2);
				}
			}
			if (!flag4)
			{
				ComboState component2 = ((Component)__instance).GetComponent<ComboState>();
				if ((Object)(object)component2 == (Object)null || !component2.Guard || Time.time > component2.LastActive + 0.5f)
				{
					Trace("skip: block neither held nor recent -> game starts a NORMAL combo hit");
					return true;
				}
			}
			SharedData val3 = __instance.GetCurrentWeapon()?.m_shared;
			if (val3 == null || val3.m_attack == null)
			{
				if (flag4)
				{
					Trace("skip: no weapon/attack");
				}
				return true;
			}
			string attackAnimation = val3.m_attack.m_attackAnimation;
			if (attackAnimation != "spearcombo" && attackAnimation != "spearguard")
			{
				if (flag4)
				{
					Trace("skip: attack name '" + attackAnimation + "' (block held) -> game starts a NORMAL hit");
				}
				return true;
			}
			object? obj = Refs.CurrentAttack?.GetValue(__instance);
			Attack val4 = (Attack)((obj is Attack) ? obj : null);
			ComboState component3 = ((Component)__instance).GetComponent<ComboState>();
			bool flag5 = (Object)(object)component3 != (Object)null && component3.GuardHolding;
			bool flag6 = val4 != null && val4.m_attackAnimation == "spearguard" && !val4.IsDone() && !flag5 && Time.time - guardStartedAt < 1.5f;
			Trace(string.Format("block(field={0},button={1}) running='{2}' ", flag2, flag3, (val4 != null) ? val4.m_attackAnimation : "<none>") + string.Format("done={0} held={1} sinceStart={2:0.00} ", (val4 != null) ? val4.IsDone().ToString() : "-", flag5, Time.time - guardStartedAt) + "-> " + (flag6 ? "REFUSE (hit still playing)" : "allow"));
			if (flag6)
			{
				__state = false;
				__result = false;
				return false;
			}
			val3.m_attack.m_attackAnimation = "spearguard";
			if (Refs.LastChainDamage != null)
			{
				Refs.LastChainDamage.Invoke(val3.m_attack) = 1f;
			}
			ComboState component4 = ((Component)__instance).GetComponent<ComboState>();
			pendingGap = (((Object)(object)component4 != (Object)null) ? (Time.time - component4.LastActive) : 999f);
			pendingContinuing = (Object)(object)component4 != (Object)null && component4.Guard && pendingGap <= Plugin.GuardReset.Value;
			if (pendingContinuing && Refs.TimeSinceLastAttack != null)
			{
				Refs.TimeSinceLastAttack.Invoke(__instance) = 0f;
			}
			object? obj2 = Refs.Zanim?.GetValue(__instance);
			ZSyncAnimation val5 = (ZSyncAnimation)((obj2 is ZSyncAnimation) ? obj2 : null);
			if (val5 != null)
			{
				if (Refs.BlockingAnimHash != null && !Plugin.KeepBlockPose.Value)
				{
					ClearBlockPose(__instance, val5);
				}
				if (Refs.AnimatorOf != null)
				{
					Animator val6 = Refs.AnimatorOf.Invoke(val5);
					if ((Object)(object)val6 != (Object)null && val6.speed < 0.01f)
					{
						val6.speed = 1f;
					}
				}
			}
			guardStartedAt = Time.time;
			__state = true;
			return true;
		}

		internal static void Finalizer(Humanoid __instance, bool __state, bool __result)
		{
			if (!__state)
			{
				return;
			}
			SharedData val = __instance.GetCurrentWeapon()?.m_shared;
			if (val == null || val.m_attack == null)
			{
				return;
			}
			val.m_attack.m_attackAnimation = "spearcombo";
			if (Refs.LastChainDamage != null)
			{
				Refs.LastChainDamage.Invoke(val.m_attack) = Plugin.LastHitDamage.Value;
			}
			if (!__result)
			{
				return;
			}
			object? obj = Refs.CurrentAttack?.GetValue(__instance);
			Attack val2 = (Attack)((obj is Attack) ? obj : null);
			if (val2 != null && val2.m_attackAnimation == "spearguard" && Refs.ChainLevel != null)
			{
				if (SwallowedSinceStart)
				{
					SwallowedSinceStart = false;
					return;
				}
				int num = Mathf.Clamp(Refs.ChainLevel.Invoke(val2), 0, 2);
				val2.m_damageMultiplier = Plugin.GuardDamage[num].Value * Plugin.BlockHitDamage.Value;
				Plugin.Log.LogDebug((object)($"Defence hit {num + 1} of 3: damage x{val2.m_damageMultiplier:0.##} " + $"(base {Plugin.GuardDamage[num].Value:0.##} x block-hit scale {Plugin.BlockHitDamage.Value:0.##}) (" + string.Format("{0}, {1:0.00}s since the last defence hit).", pendingContinuing ? "continuing the combo" : "fresh chain", pendingGap)));
			}
		}

		internal static void DamagePrefix(Character __instance)
		{
			damaged = __instance;
		}

		internal static void DamageFinalizer()
		{
			damaged = null;
		}

		internal static void IsBlockingPostfix(Humanoid __instance, ref bool __result)
		{
			if ((Object)(object)damaged != (Object)(object)__instance)
			{
				if (!__result || !((Object)(object)__instance == (Object)(object)Player.m_localPlayer))
				{
					return;
				}
				ComboState component = ((Component)__instance).GetComponent<ComboState>();
				if (component == null || !component.Guard)
				{
					return;
				}
				bool num;
				if (!HoldsShield(__instance))
				{
					if (component.Level >= 0)
					{
						goto IL_0061;
					}
					num = Time.time < component.LastActive + 0.35f;
				}
				else
				{
					num = DefenceHitRunning(__instance);
				}
				if (!num)
				{
					return;
				}
				goto IL_0061;
			}
			if (__result || !(__instance is Player) || Refs.Blocking == null || Refs.CurrentAttack == null)
			{
				return;
			}
			object value = Refs.Blocking.GetValue(__instance);
			if (value is bool && (bool)value)
			{
				object? value2 = Refs.CurrentAttack.GetValue(__instance);
				Attack val = (Attack)((value2 is Attack) ? value2 : null);
				if (val != null && !(val.m_attackAnimation != "spearguard") && !((Character)__instance).IsStaggering() && !((Character)__instance).InDodge())
				{
					__result = true;
				}
			}
			return;
			IL_0061:
			__result = false;
		}

		internal static void KeepQueuedClick(ComboState st, ZSyncAnimation zanim)
		{
			if ((Object)(object)st == (Object)null || !st.Guard || st.Level < 0 || Refs.QueuedAttack == null)
			{
				return;
			}
			Humanoid component = ((Component)zanim).GetComponent<Humanoid>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component != (Object)(object)Player.m_localPlayer))
			{
				Player val = (Player)(object)((component is Player) ? component : null);
				if (!((Object)(object)val == (Object)null) && !(Refs.QueuedAttack.Invoke(val) <= 0f))
				{
					Refs.QueuedAttack.Invoke(val) = 0.5f;
				}
			}
		}

		private static void ClearBlockPose(Humanoid h, ZSyncAnimation zanim)
		{
			if (Refs.BlockingAnimHash != null)
			{
				zanim.SetBool((int)Refs.BlockingAnimHash.GetValue(null), false);
			}
			if ((Object)(object)h != (Object)null && Refs.InternalBlocking != null)
			{
				Refs.InternalBlocking.Invoke(h) = false;
			}
		}

		internal static void SnapToBlockOnPress(ZSyncAnimation zanim, ComboState st, GameObject spear, FlipMark mark, int level)
		{
			bool flag = BlockButtonHeld();
			bool num = flag && !blockWasHeld;
			blockWasHeld = flag;
			if (!num || !Plugin.DefenceCombo.Value)
			{
				return;
			}
			Humanoid component = ((Component)zanim).GetComponent<Humanoid>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component != (Object)(object)Player.m_localPlayer) && (level >= 0 || ((Object)(object)st != (Object)null && st.Level >= 0)))
			{
				if ((Object)(object)mark != (Object)null && (Object)(object)spear != (Object)null)
				{
					mark.Flipped = true;
					mark.ReflipAt = Time.time + 1.5f;
					SpearFlip.ApplyPose(spear, mark, -1);
				}
				if (Refs.BlockingAnimHash != null)
				{
					zanim.SetBool((int)Refs.BlockingAnimHash.GetValue(null), true);
				}
				if (Refs.InternalBlocking != null)
				{
					Refs.InternalBlocking.Invoke(component) = true;
				}
				Plugin.Log.LogDebug((object)"[block] RMB during a chain - block stance snapped in (no side swing)");
			}
		}

		internal static void SuppressBlockPose(ZSyncAnimation zanim, ComboState st)
		{
			if ((Object)(object)st == (Object)null || !Plugin.DefenceCombo.Value || Refs.BlockingAnimHash == null || !st.Guard || Time.time > st.LastActive + Plugin.GuardReset.Value)
			{
				return;
			}
			Humanoid component = ((Component)zanim).GetComponent<Humanoid>();
			if ((Object)(object)component == (Object)null || (Object)(object)component != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			bool flag = default(bool);
			int num;
			if (Refs.Blocking != null)
			{
				object value = Refs.Blocking.GetValue(component);
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) == 0 && !BlockButtonHeld())
			{
				return;
			}
			if (HoldsShield(component))
			{
				object? obj = Refs.CurrentAttack?.GetValue(component);
				Attack val = (Attack)((obj is Attack) ? obj : null);
				if (val == null || val.IsDone())
				{
					ReturnToBlock(component, zanim, st);
					return;
				}
			}
			if (Plugin.KeepBlockPose.Value)
			{
				if (Refs.BlockingAnimHash != null)
				{
					zanim.SetBool((int)Refs.BlockingAnimHash.GetValue(null), true);
				}
				if (Refs.InternalBlocking != null)
				{
					Refs.InternalBlocking.Invoke(component) = true;
				}
			}
			else
			{
				ClearBlockPose(component, zanim);
			}
		}

		private static bool HoldsShield(Humanoid h)
		{
			if (!TriggerPatch.LeftHandEmpty((Component)(object)h))
			{
				return !TriggerPatch.LeftHandTorch((Component)(object)h);
			}
			return false;
		}

		private static bool DefenceHitRunning(Humanoid h)
		{
			object? obj = Refs.CurrentAttack?.GetValue(h);
			Attack val = (Attack)((obj is Attack) ? obj : null);
			if (val != null && val.m_attackAnimation == "spearguard")
			{
				return !val.IsDone();
			}
			return false;
		}

		private static void ReturnToBlock(Humanoid h, ZSyncAnimation zanim, ComboState st)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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)
			if (Refs.BlockingAnimHash != null)
			{
				zanim.SetBool((int)Refs.BlockingAnimHash.GetValue(null), true);
			}
			if (st.BlockReturned || st.Level < 0 || ((Character)h).InDodge() || Refs.AnimatorOf == null)
			{
				return;
			}
			st.BlockReturned = true;
			Animator val = Refs.AnimatorOf.Invoke(zanim);
			if (!((Object)(object)val == (Object)null) && val.HasState(0, ShieldBlockingState))
			{
				AnimatorStateInfo val2 = (val.IsInTransition(0) ? val.GetNextAnimatorStateInfo(0) : val.GetCurrentAnimatorStateInfo(0));
				if (((AnimatorStateInfo)(ref val2)).shortNameHash != ShieldBlockingState)
				{
					val.CrossFadeInFixedTime(ShieldBlockingState, 0.1f, 0);
				}
			}
		}
	}
	internal static class WiresShim
	{
		private static bool tried;

		private static float lastLogAt = -10f;

		internal static void Ensure()
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			if (tried)
			{
				return;
			}
			tried = true;
			try
			{
				Assembly assembly = null;
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly2 in assemblies)
				{
					if (assembly2.GetName().Name == "WiresCombatFlow")
					{
						assembly = assembly2;
						break;
					}
				}
				Type type = ((assembly != null) ? assembly.GetType("WiresCombatFlow.CombatFlow") : null);
				MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "TryCancel", (Type[])null, (Type[])null) : null);
				if (methodInfo == null)
				{
					Plugin.Log.LogInfo((object)"Wires Combat Flow not detected - its recovery-cancel cannot touch the defence hits.");
					return;
				}
				new Harmony("andythedemon.combospear.wires").Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(WiresShim), "TryCancelPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"Wires Combat Flow detected - its recovery-cancel is now skipped while a defence hit plays.");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not bind the Wires cancel immunity (" + ex.GetType().Name + "); defence hits stay cancellable by it."));
			}
		}

		internal static bool TryCancelPrefix(Player player, int cancel)
		{
			if ((Object)(object)player != (Object)(object)Player.m_localPlayer || Refs.CurrentAttack == null)
			{
				return true;
			}
			object? value = Refs.CurrentAttack.GetValue(player);
			Attack val = (Attack)((value is Attack) ? value : null);
			if (val == null)
			{
				return true;
			}
			ComboState component = ((Component)player).GetComponent<ComboState>();
			bool flag = ((Object)(object)component != (Object)null && component.Guard && Time.time <= component.LastActive + Plugin.GuardReset.Value) || Time.time <= GuardCombo.ArmedGuardAt + 0.5f;
			if (val.m_attackAnimation != "spearguard" && !flag)
			{
				return true;
			}
			if (Time.time - lastLogAt > 2f)
			{
				lastLogAt = Time.time;
				Plugin.Log.LogDebug((object)"Wires recovery-cancel suppressed during a defence hit (its Stop/reject/crossfade skipped).");
			}
			return false;
		}
	}
	internal static class SoftThrow
	{
		internal static void Postfix(Humanoid __instance, bool secondaryAttack, bool __result)
		{
			if (!__result || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			ComboState component = ((Component)__instance).GetComponent<ComboState>();
			if (!secondaryAttack)
			{
				object? obj = Refs.CurrentAttack?.GetValue(__instance);
				Attack val = (Attack)((obj is Attack) ? obj : null);
				if (val != null && val.m_attackAnimation == "spearcombo")
				{
					float value = Plugin.NormalHitDamage.Value;
					if (!Mathf.Approximately(value, 1f))
					{
						val.m_damageMultiplier = value;
					}
				}
			}
			else if (!((Object)(object)component == (Object)null) && component.SoftThrowPending)
			{
				component.SoftThrowPending = false;
				object? obj2 = Refs.CurrentAttack?.GetValue(__instance);
				Attack val2 = (Attack)((obj2 is Attack) ? obj2 : null);
				if (val2 != null)
				{
					val2.m_damageMultiplier = Plugin.ThrowDamage.Value;
					Plugin.Log.LogDebug((object)$"Jump-back throw damage x{Plugin.ThrowDamage.Value:0.##} (this throw only).");
				}
			}
		}
	}
	internal static class GameThrowWatch
	{
		private struct Burst
		{
			public Attack attack;

			public float at;
		}

		private static readonly List<Burst> bursts = new List<Burst>(16);

		internal static void BurstPostfix(Attack __instance)
		{
			if (__instance != null)
			{
				bursts.Add(new Burst
				{
					attack = __instance,
					at = Time.time
				});
				if (bursts.Count > 16)
				{
					bursts.RemoveAt(0);
				}
			}
		}

		internal static bool FiredSince(Attack attack, float sinceAt)
		{
			for (int num = bursts.Count - 1; num >= 0; num--)
			{
				if (bursts[num].attack == attack && bursts[num].at >= sinceAt)
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class LungeCancel
	{
		private static bool bypass;

		internal static bool InAttackPrefix(Player __instance, ref bool __result)
		{
			if (!bypass || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			__result = false;
			return false;
		}

		internal static void Prefix(Humanoid __instance, bool secondaryAttack, out bool __state)
		{
			__state = false;
			if (!secondaryAttack)
			{
				return;
			}
			if (!Plugin.JumpBackThrow.Value)
			{
				Plugin.Log.LogDebug((object)"[jg] exit: JumpBackThrow disabled");
			}
			else
			{
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				object? value = Refs.CurrentAttack.GetValue(__instance);
				Attack val = (Attack)((value is Attack) ? value : null);
				if (val == null)
				{
					Plugin.Log.LogDebug((object)"[jg] exit: current attack null");
					return;
				}
				if (val.m_attackAnimation != "spearcombo")
				{
					Plugin.Log.LogDebug((object)("[jg] exit: anim=" + val.m_attackAnimation + " want=spearcombo"));
					return;
				}
				object? value2 = Refs.Zanim.GetValue(__instance);
				ZSyncAnimation val2 = (ZSyncAnimation)((value2 is ZSyncAnimation) ? value2 : null);
				if (val2 == null)
				{
					Plugin.Log.LogDebug((object)"[jg] exit: no zanim");
				}
				else if (ComboState.LungeHitLanded(val2))
				{
					if (!((Character)__instance).IsOnGround())
					{
						Plugin.Log.LogDebug((object)"[jg] exit: airborne");
						return;
					}
					bypass = true;
					__state = true;
				}
			}
		}

		internal static void Finalizer(Humanoid __instance, bool __state, bool __result)
		{
			if (!__state)
			{
				return;
			}
			bypass = false;
			if (__result)
			{
				Plugin.Log.LogDebug((object)"Special during the lunge: lunge cut, jump-back throw started.");
				ComboState obj = ((Component)__instance).GetComponent<ComboState>() ?? ((Component)__instance).gameObject.AddComponent<ComboState>();
				obj.ThrowAt = Time.time;
				obj.PlainThrowAt = -10f;
				obj.ThrowFired = false;
				GameObject val = SpearFlip.RightItemOf((Component)(object)__instance);
				FlipMark flipMark = (((Object)(object)val != (Object)null) ? val.GetComponent<FlipMark>() : null);
				if ((Object)(object)flipMark != (Object)null)
				{
					flipMark.Flipped = true;
					flipMark.ReflipAt = Time.time + 1.6f;
				}
				Plugin.Log.LogDebug((object)string.Format("[toss] jump toss armed at {0:0.00} (item={1}, flip={2})", Time.time, ((Object)(object)val != (Object)null) ? ((Object)val).name : "null", (Object)(object)flipMark != (Object)null));
			}
			else
			{
				string text;
				try
				{
					ItemData currentWeapon = __instance.GetCurrentWeapon();
					Attack val2 = currentWeapon?.m_shared?.m_secondaryAttack;
					text = (((Character)__instance).IsStaggering() ? "the character is staggering (took a hit)" : (((Character)__instance).InDodge() ? "the character is dodging" : ((!((Character)__instance).CanMove()) ? "the character cannot move" : (((Character)__instance).InMinorAction() ? "a minor action is playing" : ((currentWeapon == null) ? "nothing in hand" : ((!currentWeapon.HaveSecondaryAttack()) ? "the weapon has no secondary attack" : ((val2 != null && !string.IsNullOrEmpty(val2.m_attackAnimation)) ? ((val2.m_cantUseInDungeon && ((Character)__instance).InInterior()) ? "the throw is blocked indoors" : ((!val2.m_requiresReload || __instance.IsWeaponLoaded()) ? "vanilla refused it, no blocking state detected" : "the weapon is not loaded")) : "the secondary attack has no animation")))))));
				}
				catch (Exception ex)
				{
					text = "state read failed (" + ex.GetType().Name + ")";
				}
				Plugin.Log.LogDebug((object)("Special during the lunge: the throw could not start - " + text + "."));
			}
		}
	}
	internal class ComboState : MonoBehaviour
	{
		public int Level = -1;

		public string Clip;

		public float CaptureAt;

		public float ExpireAt;

		public float LastActive = -10f;

		public float ThrowAt = -10f;

		public float PlainThrowAt = -10f;

		public bool ThrowFired;

		public Attack PendingThrow;

		public int PreloadedSet = -1;

		public bool Guard;

		public bool GuardHolding;

		public bool GuardHoldDone;

		public bool BlockReturned;

		public bool Exiting;

		public bool SpeedSet;

		public float GuardHoldFrom = -10f;

		public float HitAt = -1f;

		public float LungeUntil = -10f;

		public bool SoftThrowPending;

		internal static void Begin(ZSyncAnimation zanim, int level, bool guard = false)
		{
			ComboState comboState = ((Component)zanim).GetComponent<ComboState>() ?? ((Component)zanim).gameObject.AddComponent<ComboState>();
			comboState.Level = level;
			comboState.Guard = guard;
			comboState.GuardHolding = false;
			comboState.GuardHoldDone = false;
			comboState.BlockReturned = false;
			comboState.Exiting = false;
			comboState.Clip = null;
			comboState.CaptureAt = Time.time + 0.05f;
			comboState.LastActive = Time.time;
			comboState.PlainThrowAt = -10f;
			comboState.ExpireAt = Time.time + 4f;
			if (guard)
			{
				comboState.HitAt = -1f;
				comboState.LungeUntil = -10f;
			}
			else if (level >= 2)
			{
				comboState.HitAt = Time.time + 0.667f;
				comboState.LungeUntil = comboState.HitAt + 1.6f;
			}
		}

		internal static bool InThrowWindow(ZSyncAnimation zanim)
		{
			ComboState comboState = (((Object)(object)zanim != (Object)null) ? ((Component)zanim).GetComponent<ComboState>() : null);
			if ((Object)(object)comboState != (Object)null && comboState.HitAt > 0f)
			{
				return Time.time <= comboState.LungeUntil;
			}
			return false;
		}

		internal static bool LungeHitLanded(ZSyncAnimation zanim)
		{
			ComboState comboState = (((Object)(object)zanim != (Object)null) ? ((Component)zanim).GetComponent<ComboState>() : null);
			if ((Object)(object)comboState != (Object)null)
			{
				Plugin.Log.LogDebug((object)("[jumpgate] level=" + comboState.Level + " hitAt=" + comboState.HitAt.ToString("F2") + " lungeUntil=" + comboState.LungeUntil.ToString("F2") + " now=" + Time.time.ToString("F2") + " ok=" + (comboState.Level >= 2 && comboState.HitAt > 0f && Time.time >= comboState.HitAt && Time.time <= comboState.LungeUntil)));
			}
			if ((Object)(object)comboState != (Object)null && comboState.Level >= 2 && comboState.HitAt > 0f && Time.time >= comboState.HitAt)
			{
				return Time.time <= comboState.LungeUntil;
			}
			return false;
		}

		internal static void Spend(ZSyncAnimation zanim)
		{
			ComboState comboState = (((Object)(object)zanim != (Object)null) ? ((Component)zanim).GetComponent<ComboState>() : null);
			if (!((Object)(object)comboState == (Object)null))
			{
				comboState.LungeUntil = -10f;
				comboState.Level = -1;
			}
		}

		internal static void MarkSoftThrow(ZSyncAnimation zanim)
		{
			(((Component)zanim).GetComponent<ComboState>() ?? ((Component)zanim).gameObject.AddComponent<ComboState>()).SoftThrowPending = true;
		}

		internal static void Throw(ZSyncAnimation zanim)
		{
			ComboState component = ((Component)zanim).GetComponent<ComboState>();
			if ((Object)(object)component != (Object)null)
			{
				component.PreloadedSet = -1;
			}
			ComboState obj = ((Component)zanim).GetComponent<ComboState>() ?? ((Component)zanim).gameObject.AddComponent<ComboState>();
			obj.Level = -1;
			obj.LastActive = Time.time + 1f;
			obj.Exiting = false;
			obj.ThrowAt = Time.time;
			obj.PlainThrowAt = -10f;
			GameObject val = SpearFlip.RightItemOf((Component)(object)zanim);
			FlipMark flipMark = (((Object)(object)val != (Object)null) ? val.GetComponent<FlipMark>() : null);
			if ((Object)(object)flipMark != (Object)null)
			{
				flipMark.Flipped = true;
				flipMark.ReflipAt = Time.time + 1.6f;
			}
			else
			{
				Plugin.Log.LogWarning((object)"[toss] jump throw started but the spear item's FlipMark was not found");
			}
			obj.ThrowFired = false;
			obj.PendingThrow = null;
		}

		internal static void End(ZSyncAnimation zanim)
		{
			ComboState component = ((Component)zanim).GetComponent<ComboState>();
			if ((Object)(object)component != (Object)null)
			{
				component.Level = -1;
			}
		}
	}
	internal static class CustomClips
	{
		private class Slot
		{
			public AnimatorOverrideController Controller;

			public RuntimeAnimatorController Base;

			public string AppliedSignature = "";
		}

		private static AssetBundle bundle;

		private static bool bundleTried;

		private static readonly Dictionary<string, AnimationClip> clips = new Dictionary<string, AnimationClip>();

		private static readonly ConditionalWeakTable<Animator, Slot> slots = new ConditionalWeakTable<Animator, Slot>();

		internal const string EmbeddedBundleName = "spearcombo.bundle";

		private static Stream embeddedBundleStream;

		internal const string TorchSuffix = "_Torch";

		internal const string VanillaBlockHold = "Sword And Shield Idle";

		internal const string BlockHoldClip = "SpearBlockHold";

		private static bool loggedNoHold;

		private static AssetBundle LoadEmbeddedBundle()
		{
			try
			{
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				string text = null;
				string[] manifestResourceNames = executingAssembly.GetManifestResourceNames();
				foreach (string text2 in manifestResourceNames)
				{
					if (text2.EndsWith("spearcombo.bundle", StringComparison.OrdinalIgnoreCase))
					{
						text = text2;
						break;
					}
				}
				if (text == null)
				{
					return null;
				}
				using Stream stream = executingAssembly.GetManifestResourceStream(text);
				if (stream == null)
				{
					return null;
				}
				MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				memoryStream.Position = 0L;
				embeddedBundleStream = memoryStream;
				return AssetBundle.LoadFromStream((Stream)memoryStream);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not load the embedded bundle (" + ex.GetType().Name + ": " + ex.Message + ")."));
				return null;
			}
		}

		internal static AnimationClip Clip(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			if (clips.TryGetValue(name, out var value))
			{
				return value;
			}
			if (!bundleTried)
			{
				bundleTried = true;
				string text = Path.Combine(Plugin.PluginFolder, Plugin.CustomBundle.Value);
				if (File.Exists(text))
				{
					bundle = AssetBundle.LoadFromFile(text);
					Plugin.Log.Log((LogLevel)(Object.op_Implicit((Object)(object)bundle) ? 16 : 4), (object)(Object.op_Implicit((Object)(object)bundle) ? ("Loaded bundle " + text) : ("Bundle found but could not be read: " + text)));
				}
				else
				{
					bundle = LoadEmbeddedBundle();
					Plugin.Log.Log((LogLevel)(Object.op_Implicit((Object)(object)bundle) ? 16 : 4), (object)(Object.op_Implicit((Object)(object)bundle) ? "No bundle file next to the DLL - loaded the embedded copy from this assembly (release build)." : ("Bundle not found: " + text + ", and this build has no embedded bundle.")));
				}
			}
			value = (Object.op_Implicit((Object)(object)bundle) ? bundle.LoadAsset<AnimationClip>(name) : null);
			if ((Object)(object)value == (Object)null)
			{
				Plugin.Log.LogWarning((object)("Custom clip '" + name + "' not found in the bundle."));
			}
			else if (name != "SpearBlockHold" && !Array.Exists(value.events, (AnimationEvent e) => e.functionName == "OnAttackTrigger"))
			{
				Plugin.Log.LogWarning((object)("Custom clip '" + name + "' has no OnAttackTrigger event - it would never hit. Ignoring it."));
				value = null;
			}
			else
			{
				Plugin.Log.LogInfo((object)$"Custom clip '{name}' loaded ({value.length:0.00}s).");
			}
			clips[name] = value;
			return value;
		}

		internal static void Apply(Animator animator, bool on, bool freeHand = false, bool throwing = false, bool torch = false, bool guard = false)
		{
			if ((Object)(object)animator == (Object)null)
			{
				return;
			}
			List<KeyValuePair<string, AnimationClip>> pairs = new List<KeyValuePair<string, AnimationClip>>();
			if (throwing)
			{
				string name = ((freeHand && !string.IsNullOrEmpty(Plugin.ThrowCustomClipFree.Value)) ? Plugin.ThrowCustomClipFree.Value : Plugin.ThrowCustomClip.Value);
				if (torch && (Object)(object)Clip(Plugin.ThrowCustomClip.Value + "_Torch") != (Object)null)
				{
					name = Plugin.ThrowCustomClip.Value + "_Torch";
				}
				AnimationClip val = Clip(name);
				if ((Object)(object)val != (Object)null)
				{
					pairs.Add(new KeyValuePair<string, AnimationClip>(Plugin.ThrowReplacesClip.Value, val));
				}
			}
			else if (on)
			{
				string value = Plugin.PlainThrowClip.Value;
				string name2 = ((freeHand && (Object)(object)Clip(value + "_Free") != (Object)null) ? (value + "_Free") : ((torch && (Object)(object)Clip(value + "_Torch") != (Object)null) ? (value + "_Torch") : value));
				AnimationClip val2 = (string.IsNullOrEmpty(value) ? null : Clip(name2));
				if ((Object)(object)val2 != (Object)null)
				{
					pairs.Add(new KeyValuePair<string, AnimationClip>(Plugin.ThrowReplacesClip.Value, val2));
				}
			}
			if (on && !throwing)
			{
				for (int i = 0; i < 3; i++)
				{
					string value2 = Plugin.HitReplaceClip[i].Value;
					string name3 = ((freeHand && !string.IsNullOrEmpty(Plugin.HitCustomClipFree[i].Value)) ? Plugin.HitCustomClipFree[i].Value : Plugin.HitCustomClip[i].Value);
					if (guard)
					{
						string value3 = Plugin.GuardClip[i].Value;
						name3 = ((freeHand && (Object)(object)Clip(value3 + "_Free") != (Object)null) ? (value3 + "_Free") : ((torch && (Object)(object)Clip(value3 + "_Torch") != (Object)null) ? (value3 + "_Torch") : value3));
					}
					else if (torch && (Object)(object)Clip(Plugin.HitCustomClip[i].Value + "_Torch") != (Object)null)
					{
						name3 = Plugin.HitCustomClip[i].Value + "_Torch";
					}
					AnimationClip val3 = (string.IsNullOrEmpty(value2) ? null : Clip(name3));
					if ((Object)(object)val3 != (Object)null)
					{
						pairs.Add(new KeyValuePair<string, AnimationClip>(value2, val3));
					}
				}
			}
			if (on && !freeHand && !torch)
			{
				AnimationClip val4 = Clip("SpearBlockHold