Decompiled source of ComboKnife v1.0.0

BepInEx/plugins/ComboKnife.dll

Decompiled a day ago
using System;
using System.Collections;
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;
using UnityEngine.Animations;
using UnityEngine.Experimental.Animations;
using UnityEngine.Playables;
using UnityEngine.Rendering;

[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("ComboKnife")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+51bfdb3dde4ef9319b971be594d066b5026204fa")]
[assembly: AssemblyProduct("ComboKnife")]
[assembly: AssemblyTitle("ComboKnife")]
[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 ComboKnife
{
	internal class AimLayer : MonoBehaviour
	{
		private struct BendJob : IAnimationJob
		{
			public TransformStreamHandle spine;

			public TransformStreamHandle spine1;

			public TransformStreamHandle spine2;

			public Vector3 axis;

			public float pitch;

			public void ProcessRootMotion(AnimationStream stream)
			{
			}

			public void ProcessAnimation(AnimationStream stream)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: 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)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: 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)
				if (!(Mathf.Abs(pitch) < 0.05f))
				{
					Bend(stream, spine, AimMath.SpineShare[0]);
					Bend(stream, spine1, AimMath.SpineShare[1]);
					Bend(stream, spine2, AimMath.SpineShare[2]);
				}
			}

			private void Bend(AnimationStream stream, TransformStreamHandle h, float share)
			{
				//IL_0002: 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_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: 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_002a: Unknown result type (might be due to invalid IL or missing references)
				if (((TransformStreamHandle)(ref h)).IsValid(stream))
				{
					((TransformStreamHandle)(ref h)).SetRotation(stream, Quaternion.AngleAxis((0f - pitch) * share, axis) * ((TransformStreamHandle)(ref h)).GetRotation(stream));
				}
			}
		}

		private static readonly int ZdoKey = StringExtensionMethods.GetStableHashCode("comboknife_aim");

		private static readonly string[] SpineBones = new string[3] { "Spine", "Spine1", "Spine2" };

		private Humanoid owner;

		private ZNetView nview;

		private Animator animator;

		private RuntimeAnimatorController boundTo;

		private PlayableGraph graph;

		private AnimationScriptPlayable playable;

		private RuntimeAnimatorController failedFor;

		private bool stale;

		private bool bending;

		private float weight;

		private float shown;

		private float sent;

		internal static void Invalidate(Animator a)
		{
			AimLayer aimLayer = (((Object)(object)a != (Object)null) ? ((Component)a).GetComponent<AimLayer>() : null);
			if ((Object)(object)aimLayer != (Object)null)
			{
				aimLayer.stale = true;
			}
		}

		internal static void PlayerAwakePostfix(Player __instance)
		{
			Animator val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInChildren<Animator>() : null);
			if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent<AimLayer>() == (Object)null)
			{
				((Component)val).gameObject.AddComponent<AimLayer>();
			}
		}

		private void Start()
		{
			owner = ((Component)this).GetComponentInParent<Humanoid>();
			nview = (((Object)(object)owner != (Object)null) ? ((Component)owner).GetComponent<ZNetView>() : null);
			animator = ((Component)this).GetComponent<Animator>();
		}

		private void Update()
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)owner == (Object)null) && !((Object)(object)nview == (Object)null) && nview.IsValid() && !((Object)(object)animator == (Object)null))
			{
				float num = (nview.IsOwner() ? OwnPitch() : nview.GetZDO().GetFloat(ZdoKey, 0f));
				bool flag = Mathf.Abs(num) > 0.05f;
				if (flag && !bending)
				{
					stale = true;
				}
				bending = flag;
				shown = Mathf.Lerp(shown, num, 1f - Mathf.Exp(-10f * Time.deltaTime));
				if (EnsureGraph())
				{
					BendJob jobData = ((AnimationScriptPlayable)(ref playable)).GetJobData<BendJob>();
					jobData.pitch = shown;
					jobData.axis = ((Component)owner).transform.right;
					((AnimationScriptPlayable)(ref playable)).SetJobData<BendJob>(jobData);
				}
			}
		}

		private bool EnsureGraph()
		{
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController;
			if (((PlayableGraph)(ref graph)).IsValid() && (Object)(object)boundTo == (Object)(object)runtimeAnimatorController && !stale)
			{
				return true;
			}
			if (!stale && (Object)(object)failedFor != (Object)null && (Object)(object)failedFor == (Object)(object)runtimeAnimatorController)
			{
				return false;
			}
			stale = false;
			DestroyGraph();
			Transform[] array = (Transform[])(object)new Transform[3];
			Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				int num = Array.IndexOf(SpineBones, ((Object)val).name);
				if (num >= 0 && (Object)(object)array[num] == (Object)null && val.IsChildOf(((Component)this).transform))
				{
					array[num] = val;
				}
			}
			if ((Object)(object)array[0] == (Object)null || (Object)(object)array[1] == (Object)null || (Object)(object)array[2] == (Object)null)
			{
				failedFor = runtimeAnimatorController;
				return false;
			}
			failedFor = null;
			BendJob bendJob = new BendJob
			{
				spine = AnimatorJobExtensions.BindStreamTransform(animator, array[0]),
				spine1 = AnimatorJobExtensions.BindStreamTransform(animator, array[1]),
				spine2 = AnimatorJobExtensions.BindStreamTransform(animator, array[2])
			};
			graph = PlayableGraph.Create("ComboKnife aim");
			((PlayableGraph)(ref graph)).SetTimeUpdateMode((DirectorUpdateMode)1);
			playable = AnimationScriptPlayable.Create<BendJob>(graph, bendJob, 0);
			AnimationPlayableOutput val2 = AnimationPlayableOutput.Create(graph, "aim", animator);
			PlayableOutputExtensions.SetSourcePlayable<AnimationPlayableOutput, AnimationScriptPlayable>(val2, playable);
			AnimationPlayableOutputExtensions.SetAnimationStreamSource(val2, (AnimationStreamSource)1);
			((PlayableGraph)(ref graph)).Play();
			boundTo = runtimeAnimatorController;
			return true;
		}

		private void DestroyGraph()
		{
			if (((PlayableGraph)(ref graph)).IsValid())
			{
				((PlayableGraph)(ref graph)).Destroy();
			}
		}

		private void OnDestroy()
		{
			DestroyGraph();
		}

		private float OwnPitch()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			bool attacking = Specials.InOwnMove(owner);
			weight = AimMath.Blend(weight, attacking, Time.deltaTime);
			float num = weight * AimMath.Pitch(((Character)owner).GetLookDir().y);
			if (AimMath.ShouldSync(sent, num))
			{
				nview.GetZDO().Set(ZdoKey, num);
				sent = num;
			}
			return num;
		}
	}
	public static class AimMath
	{
		public const float MaxPitch = 40f;

		public const float MaxBendUp = 20f;

		public const float MaxBendDown = 35f;

		public const float BlendRate = 8f;

		public static readonly float[] SpineShare = new float[3] { 0.25f, 0.35f, 0.4f };

		public const float Smoothing = 10f;

		public const float SyncStep = 1f;

		public static float Pitch(float lookY)
		{
			float val = (float)(Math.Asin(Math.Max(-1f, Math.Min(1f, lookY))) * 180.0 / Math.PI);
			return Math.Max(-35f, Math.Min(20f, val));
		}

		public static float Blend(float weight, bool attacking, float dt)
		{
			float num = 8f * Math.Max(0f, dt);
			if (!attacking)
			{
				return Math.Max(0f, weight - num);
			}
			return Math.Min(1f, weight + num);
		}

		public static bool ShouldSync(float sent, float now)
		{
			if (!(Math.Abs(now - sent) >= 1f))
			{
				if (now == 0f)
				{
					return sent != 0f;
				}
				return false;
			}
			return true;
		}
	}
	internal static class ClipSets
	{
		private class Own
		{
			public AnimatorOverrideController Controller;

			public RuntimeAnimatorController Base;
		}

		internal const string BundleFile = "comboknife.bundle";

		private static AssetBundle bundle;

		private static bool bundleTried;

		private static Stream embeddedBundleStream;

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

		private static readonly ConditionalWeakTable<Animator, Own> own = new ConditionalWeakTable<Animator, Own>();

		private static readonly Move[] Moves = new Move[9]
		{
			Move.L1,
			Move.L2,
			Move.L3,
			Move.S1,
			Move.S2,
			Move.S3,
			Move.H1,
			Move.H2,
			Move.H3
		};

		internal const string LeapH1Name = "BladeH1_Leap";

		internal const string LeapSource = "Knife Attack Leap";

		internal const float LeapChainAfterHit = 0.1f;

		private static AnimationClip leapH1;

		private static readonly Dictionary<SetKey, HashSet<string>> ownNames = new Dictionary<SetKey, HashSet<string>>();

		internal static string ResolveName(SetKey key, Move m)
		{
			if (m == Move.H1)
			{
				return "BladeH1_Leap";
			}
			string text = Families.ClipName(key.Family, m, key.Variant);
			if (key.Variant != Variant.Free && (Object)(object)Clip(text) == (Object)null)
			{
				text = Families.ClipName(key.Family, m);
			}
			return text;
		}

		private static AnimationClip Resolve(SetKey key, Move m)
		{
			if (m != Move.H1)
			{
				return Clip(ResolveName(key, m));
			}
			return leapH1;
		}

		private static void EnsureLeap(Animator animator)
		{
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Expected O, but got Unknown
			if ((Object)(object)leapH1 != (Object)null || (Object)(object)animator == (Object)null || (Object)(object)animator.runtimeAnimatorController == (Object)null)
			{
				return;
			}
			AnimationClip val = null;
			AnimationClip[] animationClips = animator.runtimeAnimatorController.animationClips;
			foreach (AnimationClip val2 in animationClips)
			{
				if ((Object)(object)val2 != (Object)null && ((Object)val2).name == "Knife Attack Leap")
				{
					val = val2;
					break;
				}
			}
			RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController;
			AnimatorOverrideController val3 = (AnimatorOverrideController)(object)((runtimeAnimatorController is AnimatorOverrideController) ? runtimeAnimatorController : null);
			if ((Object)(object)val == (Object)null && (Object)(object)val3 != (Object)null && (Object)(object)val3.runtimeAnimatorController != (Object)null)
			{
				animationClips = val3.runtimeAnimatorController.animationClips;
				foreach (AnimationClip val4 in animationClips)
				{
					if ((Object)(object)val4 != (Object)null && ((Object)val4).name == "Knife Attack Leap")
					{
						val = val4;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"'Knife Attack Leap' not found: H1 keeps the bundle clip.");
				return;
			}
			AnimationClip val5 = Object.Instantiate<AnimationClip>(val);
			((Object)val5).name = "BladeH1_Leap";
			float num = -1f;
			List<AnimationEvent> list = new List<AnimationEvent>();
			AnimationEvent[] events = val.events;
			foreach (AnimationEvent val6 in events)
			{
				if (!(val6.functionName == "Chain"))
				{
					if (num < 0f && (val6.functionName == "OnAttackTrigger" || val6.functionName == "Hit" || val6.functionName.Contains("Attack")))
					{
						num = val6.time;
					}
					list.Add(val6);
				}
			}
			float num2 = ((num >= 0f) ? Mathf.Min(num + 0.1f, val.length - 0.05f) : (val.length * 0.7f));
			list.Add(new AnimationEvent
			{
				functionName = "Chain",
				time = num2
			});
			list.Sort((AnimationEvent a, AnimationEvent b) => a.time.CompareTo(b.time));
			val5.events = list.ToArray();
			leapH1 = val5;
			StringBuilder stringBuilder = new StringBuilder();
			events = val.events;
			foreach (AnimationEvent val7 in events)
			{
				stringBuilder.Append(' ').Append(val7.functionName).Append('@')
					.Append(val7.time.ToString("0.00"));
			}
			Plugin.Log.LogInfo((object)string.Format("H1 = vanilla '{0}' ({1:0.00} s, hit {2:0.00} s, chain {3:0.00} s; events:{4})", "Knife Attack Leap", val.length, num, num2, stringBuilder));
		}

		internal static bool IsOwnClip(SetKey key, string clip)
		{
			if (clip == null)
			{
				return false;
			}
			if (!ownNames.TryGetValue(key, out var value))
			{
				value = new HashSet<string>();
				Move[] moves = Moves;
				foreach (Move m in moves)
				{
					value.Add(ResolveName(key, m));
				}
				if (Object.op_Implicit((Object)(object)bundle))
				{
					ownNames[key] = value;
				}
			}
			return value.Contains(clip);
		}

		internal static TextAsset ReadTextAsset(string path)
		{
			if (!Object.op_Implicit((Object)(object)bundle))
			{
				return null;
			}
			return bundle.LoadAsset<TextAsset>(path);
		}

		internal static T ReadAsset<T>(string path) where T : Object
		{
			if (!bundleTried)
			{
				Clip(Families.ClipName(Family.Blade, Move.L1));
			}
			if (!Object.op_Implicit((Object)(object)bundle))
			{
				return default(T);
			}
			return bundle.LoadAsset<T>(path);
		}

		internal static bool AllBaseClipsPresent(out string missing)
		{
			List<string> list = new List<string>();
			Family[] array = new Family[2]
			{
				Family.Blade,
				Family.Twin
			};
			foreach (Family f in array)
			{
				Move[] moves = Moves;
				foreach (Move move in moves)
				{
					if (move == Move.H1)
					{
						continue;
					}
					string text = Families.ClipName(f, move);
					if (!((Object)(object)Clip(text) != (Object)null))
					{
						if (move == Move.S1)
						{
							Plugin.Log.LogWarning((object)(text + " is not in the bundle yet - S1 plays the vanilla host clip."));
						}
						else
						{
							list.Add(text);
						}
					}
				}
			}
			missing = string.Join(", ", list.ToArray());
			return list.Count == 0;
		}

		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 ?? "", "comboknife.bundle");
				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." : ("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)
			{
				bool flag = name.EndsWith("_Shield", StringComparison.Ordinal) || name.EndsWith("_Torch", StringComparison.Ordinal);
				Plugin.Log.Log((LogLevel)(flag ? 32 : 4), (object)("Custom clip '" + name + "' not found in the bundle."));
			}
			else if (!Array.Exists(value.events, (AnimationEvent e) => e.functionName == "OnAttackTrigger" || e.functionName == "ThrowRelease" || e.functionName == "VeilVanish"))
			{
				Plugin.Log.LogWarning((object)("Custom clip '" + name + "' has no OnAttackTrigger event - it would never hit. Ignoring it."));
				value = null;
			}
			else
			{
				Plugin.Log.LogDebug((object)$"Custom clip '{name}' loaded ({value.length:0.00}s).");
			}
			clips[name] = value;
			return value;
		}

		private static AssetBundle LoadEmbeddedBundle()
		{
			try
			{
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				string text = null;
				string[] manifestResourceNames = executingAssembly.GetManifestResourceNames();
				foreach (string text2 in manifestResourceNames)
				{
					if (text2.EndsWith("comboknife.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;
			}
		}

		private static Dictionary<string, AnimationClip> Pairs(SetKey? key)
		{
			Dictionary<string, AnimationClip> dictionary = new Dictionary<string, AnimationClip>();
			if (!key.HasValue)
			{
				return dictionary;
			}
			Move[] moves = Moves;
			foreach (Move m in moves)
			{
				AnimationClip val = Resolve(key.Value, m);
				if ((Object)(object)val != (Object)null)
				{
					dictionary[Families.HostClip(m)] = val;
				}
			}
			return dictionary;
		}

		internal static void Apply(Animator animator, SetKey? key)
		{
			if ((Object)(object)animator == (Object)null)
			{
				return;
			}
			EnsureLeap(animator);
			Dictionary<string, AnimationClip> want = Pairs(key);
			AnimatorOverrideController aoc = default(AnimatorOverrideController);
			ref AnimatorOverrideController reference = ref aoc;
			RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController;
			reference = (AnimatorOverrideController)(object)((runtimeAnimatorController is AnimatorOverrideController) ? runtimeAnimatorController : null);
			if ((Object)(object)aoc == (Object)null)
			{
				if (want.Count == 0)
				{
					return;
				}
				aoc = Wrap(animator);
				if ((Object)(object)aoc == (Object)null)
				{
					return;
				}
			}
			if (!Matches(aoc, want))
			{
				Preserving(animator, delegate
				{
					Write(aoc, want);
				});
			}
			if (want.Count == 0)
			{
				Unwrap(animator);
			}
		}

		internal static bool OursPresent(Animator animator, SetKey key)
		{
			AnimatorOverrideController val = (AnimatorOverrideController)(((Object)(object)animator != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			Dictionary<string, AnimationClip> dictionary = Pairs(key);
			if ((Object)(object)val != (Object)null && dictionary.Count > 0)
			{
				return Matches(val, dictionary);
			}
			return false;
		}

		private static bool IsHost(string clipName)
		{
			Move[] moves = Moves;
			for (int i = 0; i < moves.Length; i++)
			{
				if (Families.HostClip(moves[i]) == clipName)
				{
					return true;
				}
			}
			return false;
		}

		private static bool Matches(AnimatorOverrideController aoc, Dictionary<string, AnimationClip> want)
		{
			List<KeyValuePair<AnimationClip, AnimationClip>> list = new List<KeyValuePair<AnimationClip, AnimationClip>>();
			aoc.GetOverrides(list);
			foreach (KeyValuePair<AnimationClip, AnimationClip> item in list)
			{
				if (!((Object)(object)item.Key == (Object)null) && IsHost(((Object)item.Key).name))
				{
					want.TryGetValue(((Object)item.Key).name, out var value);
					if ((Object)(object)item.Value != (Object)(object)value)
					{
						return false;
					}
				}
			}
			return true;
		}

		private static void Write(AnimatorOverrideController aoc, Dictionary<string, AnimationClip> want)
		{
			List<KeyValuePair<AnimationClip, AnimationClip>> list = new List<KeyValuePair<AnimationClip, AnimationClip>>();
			aoc.GetOverrides(list);
			for (int i = 0; i < list.Count; i++)
			{
				AnimationClip key = list[i].Key;
				if (!((Object)(object)key == (Object)null) && IsHost(((Object)key).name))
				{
					want.TryGetValue(((Object)key).name, out var value);
					list[i] = new KeyValuePair<AnimationClip, AnimationClip>(key, value);
				}
			}
			aoc.ApplyOverrides((IList<KeyValuePair<AnimationClip, AnimationClip>>)list);
		}

		private static AnimatorOverrideController Wrap(Animator animator)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController;
			if ((Object)(object)runtimeAnimatorController == (Object)null)
			{
				return null;
			}
			AnimatorOverrideController controller = new AnimatorOverrideController(runtimeAnimatorController)
			{
				name = ((Object)runtimeAnimatorController).name + " (ComboKnife)"
			};
			Preserving(animator, delegate
			{
				animator.runtimeAnimatorController = (RuntimeAnimatorController)(object)controller;
			});
			own.Remove(animator);
			own.Add(animator, new Own
			{
				Controller = controller,
				Base = runtimeAnimatorController
			});
			return controller;
		}

		private static void Unwrap(Animator animator)
		{
			if (!own.TryGetValue(animator, out var o))
			{
				return;
			}
			if ((Object)(object)animator.runtimeAnimatorController != (Object)(object)o.Controller)
			{
				own.Remove(animator);
				return;
			}
			List<KeyValuePair<AnimationClip, AnimationClip>> list = new List<KeyValuePair<AnimationClip, AnimationClip>>();
			o.Controller.GetOverrides(list);
			foreach (KeyValuePair<AnimationClip, AnimationClip> item in list)
			{
				if ((Object)(object)item.Value != (Object)null)
				{
					return;
				}
			}
			Preserving(animator, delegate
			{
				animator.runtimeAnimatorController = o.Base;
			});
			own.Remove(animator);
		}

		private static void Preserving(Animator animator, Action change)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected I4, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected I4, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			int layerCount = animator.layerCount;
			AnimatorStateInfo[] array = (AnimatorStateInfo[])(object)new AnimatorStateInfo[layerCount];
			float[] array2 = new float[layerCount];
			for (int i = 0; i < layerCount; i++)
			{
				array[i] = (animator.IsInTransition(i) ? animator.GetNextAnimatorStateInfo(i) : animator.GetCurrentAnimatorStateInfo(i));
				array2[i] = animator.GetLayerWeight(i);
			}
			AnimatorControllerParameter[] parameters = animator.parameters;
			float[] array3 = new float[parameters.Length];
			for (int j = 0; j < parameters.Length; j++)
			{
				AnimatorControllerParameterType type = parameters[j].type;
				switch (type - 1)
				{
				case 0:
					array3[j] = animator.GetFloat(parameters[j].nameHash);
					break;
				case 2:
					array3[j] = animator.GetInteger(parameters[j].nameHash);
					break;
				case 3:
					array3[j] = (animator.GetBool(parameters[j].nameHash) ? 1f : 0f);
					break;
				}
			}
			float speed = animator.speed;
			change();
			AimLayer.Invalidate(animator);
			animator.Update(0f);
			for (int k = 0; k < parameters.Length; k++)
			{
				AnimatorControllerParameterType type = parameters[k].type;
				switch (type - 1)
				{
				case 0:
					animator.SetFloat(parameters[k].nameHash, array3[k]);
					break;
				case 2:
					animator.SetInteger(parameters[k].nameHash, (int)array3[k]);
					break;
				case 3:
					animator.SetBool(parameters[k].nameHash, array3[k] != 0f);
					break;
				}
			}
			for (int l = 0; l < layerCount && l < animator.layerCount; l++)
			{
				animator.SetLayerWeight(l, array2[l]);
				AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(l);
				if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash != ((AnimatorStateInfo)(ref array[l])).fullPathHash)
				{
					animator.Play(((AnimatorStateInfo)(ref array[l])).fullPathHash, l, ((AnimatorStateInfo)(ref array[l])).normalizedTime);
				}
			}
			animator.speed = speed;
		}
	}
	public enum Move
	{
		None,
		L1,
		L2,
		L3,
		S1,
		S2,
		S3,
		H1,
		H2,
		H3
	}
	public enum Press
	{
		Primary,
		Special
	}
	public static class ComboGraph
	{
		public static Move Next(Move current, Press press, bool inWindow)
		{
			if (press == Press.Primary)
			{
				if (!inWindow)
				{
					return Move.L1;
				}
				return current switch
				{
					Move.L1 => Move.L2, 
					Move.L2 => Move.L3, 
					_ => Move.L1, 
				};
			}
			if (!inWindow)
			{
				return Move.H1;
			}
			return current switch
			{
				Move.L1 => Move.S1, 
				Move.L2 => Move.S2, 
				Move.L3 => Move.S3, 
				Move.H1 => Move.H2, 
				Move.H2 => Move.H3, 
				_ => Move.H1, 
			};
		}

		public static bool ChainsAtChainPoint(Move current, Press press)
		{
			if (press == Press.Primary)
			{
				if (current != Move.L1)
				{
					return current == Move.L2;
				}
				return true;
			}
			if (current != Move.L1 && current != Move.L2 && current != Move.L3 && current != Move.H1)
			{
				return current == Move.H2;
			}
			return true;
		}

		public static bool IsFinisher(Move m)
		{
			if (m != Move.S1 && m != Move.S2)
			{
				return m == Move.S3;
			}
			return true;
		}
	}
	internal class ComboState : MonoBehaviour
	{
		internal SetKey Key;

		internal SetKey? PrevKey;

		internal Move Current;

		internal bool Running;

		internal string Clip;

		internal bool Exiting;

		internal float StartedAt = -10f;

		internal float CaptureAt;

		internal float LastActive = -10f;

		internal float EndedAt = -10f;

		internal float AbsentSince = -1f;

		internal string LastTrigger;

		internal float LastTriggerAt = -10f;

		internal SetKey? Preloaded;

		internal SetKey? RemoteApplied;

		internal float NextPreload;

		internal readonly Dictionary<string, float> Pending = new Dictionary<string, float>();

		internal readonly Dictionary<string, int> PendingCombo = new Dictionary<string, int>();

		internal int ComboId;

		internal static ComboState Of(Component c)
		{
			ComboState component = c.GetComponent<ComboState>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			if ((Object)(object)c.GetComponent<KnifeGrip>() == (Object)null)
			{
				c.gameObject.AddComponent<KnifeGrip>();
			}
			return c.gameObject.AddComponent<ComboState>();
		}

		internal void Begin(SetKey key, Move move)
		{
			if (!key.Equals(Key))
			{
				PrevKey = Key;
			}
			Key = key;
			Current = move;
			Running = true;
			Clip = null;
			Exiting = false;
			StartedAt = (LastActive = Time.time);
			CaptureAt = Time.time + 0.05f;
			AbsentSince = -1f;
		}
	}
	public enum Family
	{
		Blade,
		Twin
	}
	public enum Variant
	{
		Shield,
		Free,
		Torch
	}
	public static class Families
	{
		public const string Prefix = "comboknife_";

		public const string BladeAttack = "knife_stab";

		public const string TwinAttack = "dual_knives";

		internal static readonly string[,] Hosts = new string[9, 3]
		{
			{ "dualaxes0", "DualAxes Attack 1", "chain 0->1->2 MEASURED, speed 1.00, travel ~0.5 m" },
			{ "dualaxes1", "DualAxes Attack 2 2", "chain MEASURED, speed 1.00" },
			{ "dualaxes2", "DualAxes Attack 3 2", "chain MEASURED, speed 1.00" },
			{ "dual_knives_secondary", "Knife Attack Leap", "speed 1.00, starts from L1-L3 MEASURED" },
			{ "shovel_secondary", "Attack Shovel Secondary", "speed 1.00, starts from L1-L3 MEASURED, travel 0" },
			{ "atgeir_secondary", "Atgeir360Attack", "speed 1.00, starts from L1-L3 MEASURED" },
			{ "dual_knives0", "Knife Attack Combo (1)", "chain MEASURED, speed 1.10: author clips x1.10 long" },
			{ "dual_knives1", "Knife Attack Combo (2)", "chain MEASURED, speed 1.10" },
			{ "dual_knives2", "Knife Attack Combo (3)", "chain MEASURED, speed 1.10" }
		};

		public static readonly Move[] Moves = new Move[9]
		{
			Move.L1,
			Move.L2,
			Move.L3,
			Move.S1,
			Move.S2,
			Move.S3,
			Move.H1,
			Move.H2,
			Move.H3
		};

		public const float ThrowDamageFactor = 0.5f;

		public const float LastChainBonus = 1f;

		public static Family? Detect(bool knivesSkill, bool oneHanded, bool twoHanded, string attack)
		{
			if (!knivesSkill)
			{
				return null;
			}
			if (oneHanded && attack == "knife_stab")
			{
				return Family.Blade;
			}
			if (twoHanded && attack == "dual_knives")
			{
				return Family.Twin;
			}
			return null;
		}

		public static string AttackName(Family f)
		{
			if (f != Family.Blade)
			{
				return "comboknife_twin";
			}
			return "comboknife_blade";
		}

		public static string SpecialTrigger(Family f, Move m)
		{
			switch (m)
			{
			case Move.S1:
			case Move.S2:
			case Move.S3:
				return AttackName(f) + "_s" + (int)(m - 4 + 1);
			case Move.H1:
			case Move.H2:
			case Move.H3:
				return AttackName(f) + "_h" + (int)(m - 7 + 1);
			default:
				return null;
			}
		}

		public static bool ParseTrigger(string trigger, out Family family, out Move move)
		{
			family = Family.Blade;
			move = Move.None;
			if (trigger == null || !trigger.StartsWith("comboknife_", StringComparison.Ordinal))
			{
				return false;
			}
			Family[] array = new Family[2]
			{
				Family.Blade,
				Family.Twin
			};
			int num = 0;
			while (num < array.Length)
			{
				Family family2 = array[num];
				string text = AttackName(family2);
				string text2;
				if (trigger.StartsWith(text, StringComparison.Ordinal))
				{
					text2 = trigger.Substring(text.Length);
					if (text2 == null)
					{
						goto IL_0142;
					}
					int length = text2.Length;
					if (length != 1)
					{
						if (length != 3)
						{
							goto IL_0142;
						}
						switch (text2[2])
						{
						case '1':
							break;
						case '2':
							goto IL_00d8;
						case '3':
							goto IL_00f6;
						default:
							goto IL_0142;
						}
						if (!(text2 == "_s1"))
						{
							if (!(text2 == "_h1"))
							{
								goto IL_0142;
							}
							move = Move.H1;
						}
						else
						{
							move = Move.S1;
						}
					}
					else
					{
						switch (text2[0])
						{
						case '0':
							break;
						case '1':
							goto IL_0119;
						case '2':
							goto IL_011e;
						default:
							goto IL_0142;
						}
						move = Move.L1;
					}
					goto IL_0144;
				}
				num++;
				continue;
				IL_0142:
				return false;
				IL_0119:
				move = Move.L2;
				goto IL_0144;
				IL_00d8:
				if (!(text2 == "_s2"))
				{
					if (!(text2 == "_h2"))
					{
						goto IL_0142;
					}
					move = Move.H2;
				}
				else
				{
					move = Move.S2;
				}
				goto IL_0144;
				IL_011e:
				move = Move.L3;
				goto IL_0144;
				IL_0144:
				family = family2;
				return true;
				IL_00f6:
				if (!(text2 == "_s3"))
				{
					if (!(text2 == "_h3"))
					{
						goto IL_0142;
					}
					move = Move.H3;
				}
				else
				{
					move = Move.S3;
				}
				goto IL_0144;
			}
			return false;
		}

		public static string Suffix(Variant v)
		{
			return v switch
			{
				Variant.Torch => "_Torch", 
				Variant.Shield => "_Shield", 
				_ => "", 
			};
		}

		public static string ClipName(Family f, Move m, Variant v = Variant.Free)
		{
			return f.ToString() + m.ToString() + ((f == Family.Blade) ? Suffix(v) : "");
		}

		public static string HostTrigger(Move m)
		{
			if (m != Move.None)
			{
				return Hosts[(int)(m - 1), 0];
			}
			return null;
		}

		public static string HostClip(Move m)
		{
			if (m != Move.None)
			{
				return Hosts[(int)(m - 1), 1];
			}
			return null;
		}

		public static string HostStatus(Move m)
		{
			if (m != Move.None)
			{
				return Hosts[(int)(m - 1), 2];
			}
			return null;
		}

		public static bool ParseClip(string clip, out Move move)
		{
			move = Move.None;
			if (clip == null)
			{
				return false;
			}
			string text = (clip.StartsWith("Blade", StringComparison.Ordinal) ? clip.Substring(5) : (clip.StartsWith("Twin", StringComparison.Ordinal) ? clip.Substring(4) : null));
			if (text == null || text.Length < 2)
			{
				return false;
			}
			int num = text.IndexOf('_');
			string text2 = ((num < 0) ? text : text.Substring(0, num));
			Move[] moves = Moves;
			for (int i = 0; i < moves.Length; i++)
			{
				Move move2 = moves[i];
				if (move2.ToString() == text2)
				{
					move = move2;
					return true;
				}
			}
			return false;
		}

		public static bool IsHostClip(string clip)
		{
			Move[] moves = Moves;
			for (int i = 0; i < moves.Length; i++)
			{
				if (HostClip(moves[i]) == clip)
				{
					return true;
				}
			}
			return false;
		}

		public static bool IsHostTrigger(string trigger)
		{
			Move[] moves = Moves;
			for (int i = 0; i < moves.Length; i++)
			{
				if (HostTrigger(moves[i]) == trigger)
				{
					return true;
				}
			}
			return false;
		}

		public static float Damage(Family f, Move m)
		{
			return m switch
			{
				Move.L1 => 1f, 
				Move.L2 => 1.1f, 
				Move.L3 => 1.25f, 
				Move.S1 => 1.65f, 
				Move.S2 => 1.45f, 
				Move.S3 => 2.2f, 
				Move.H1 => 1.5f, 
				Move.H2 => 1.65f, 
				Move.H3 => 2.1f, 
				_ => 1f, 
			};
		}

		public static float Stamina(Move m)
		{
			return m switch
			{
				Move.L1 => 8f, 
				Move.L2 => 9f, 
				Move.L3 => 11f, 
				Move.S1 => 18f, 
				Move.S2 => 19f, 
				Move.S3 => 23f, 
				Move.H1 => 17f, 
				Move.H2 => 18f, 
				Move.H3 => 24f, 
				_ => 0f, 
			};
		}

		public static float ThrowDamagePerKnife(Family f)
		{
			return ((f == Family.Twin) ? 1.275f : 1.65f) * 0.5f;
		}
	}
	internal static class FamilyItems
	{
		private static readonly Dictionary<SharedData, Family> families = new Dictionary<SharedData, Family>();

		internal static void ObjectDBPostfix(ObjectDB __instance)
		{
			Register(__instance);
		}

		internal static void Register(ObjectDB db)
		{
			if ((Object)(object)db == (Object)null || db.m_items == null)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			foreach (GameObject item in db.m_items)
			{
				if (!((Object)(object)item == (Object)null))
				{
					Family? family = Apply(item.GetComponent<ItemDrop>()?.m_itemData?.m_shared);
					if (family == Family.Blade)
					{
						num++;
					}
					else if (family == Family.Twin)
					{
						num2++;
					}
				}
			}
			Plugin.Log.LogInfo((object)$"Blade family on {num} knives, Twin family on {num2} dual knives.");
		}

		internal static Family? FamilyOf(ItemData item)
		{
			return Apply(item?.m_shared);
		}

		private static Family? Apply(SharedData s)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			if (s == null || s.m_attack == null)
			{
				return null;
			}
			if (families.TryGetValue(s, out var value))
			{
				return value;
			}
			bool flag = (int)s.m_skillType == 2;
			bool flag2 = (int)s.m_itemType == 3;
			bool flag3 = (int)s.m_itemType == 14;
			string attackAnimation = s.m_attack.m_attackAnimation;
			Family? result = Families.Detect(flag, flag2, flag3, attackAnimation);
			if (!result.HasValue && flag)
			{
				if (flag2 && attackAnimation == Families.AttackName(Family.Blade))
				{
					result = Family.Blade;
				}
				else if (flag3 && attackAnimation == Families.AttackName(Family.Twin))
				{
					result = Family.Twin;
				}
			}
			if (!result.HasValue)
			{
				return null;
			}
			families[s] = result.Value;
			s.m_attack.m_attackAnimation = Families.AttackName(result.Value);
			if (s.m_attack.m_attackChainLevels != 3)
			{
				Plugin.Log.LogWarning((object)$"{s.m_name}: vanilla m_attackChainLevels is {s.m_attack.m_attackChainLevels}, not 3 - L3 may be unreachable (left as is).");
			}
			return result;
		}
	}
	internal static class HitTracking
	{
		internal static string LastOwnClip = "";

		private const float NeverShowedUp = 1.5f;

		private const float PreloadAfter = 0.3f;

		private const float PreloadEvery = 0.25f;

		private const float EndGrace = 0.15f;

		private static readonly List<string> scratch = new List<string>();

		internal static void SyncPostfix(ZSyncAnimation __instance)
		{
			ComboState component = ((Component)__instance).GetComponent<ComboState>();
			if ((Object)(object)component != (Object)null && component.Running)
			{
				Track(__instance, component);
			}
			if ((Object)(object)component != (Object)null && component.Pending.Count > 0)
			{
				ClearStale(__instance, component);
			}
			Preload(__instance, component);
		}

		private static void Track(ZSyncAnimation z, ComboState st)
		{
			if (st.Clip == null && Time.time > st.StartedAt + 1.5f)
			{
				if ((Object)(object)((Component)z).GetComponent<Player>() != (Object)(object)Player.m_localPlayer)
				{
					Plugin.Log.LogDebug((object)$"[MP] {((Object)z).name} {st.Key.Family}{st.Current} never played (its clip did not show up)");
				}
				End(st);
			}
			else
			{
				if (Time.time < st.CaptureAt || Refs.AnimatorOf == null)
				{
					return;
				}
				Animator val = Refs.AnimatorOf.Invoke(z);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				string text = TopClip(val.GetCurrentAnimatorClipInfo(0));
				string text2 = (val.IsInTransition(0) ? TopClip(val.GetNextAnimatorClipInfo(0)) : null);
				if (st.Clip == null)
				{
					string text3 = ClipSets.ResolveName(st.Key, st.Current);
					if (text != text3 && text2 != text3)
					{
						return;
					}
					st.Clip = text3;
					if (TriggerHygiene.StartsFresh(st.Current))
					{
						ClearOrphans(z, val, st);
					}
					if ((Object)(object)((Component)z).GetComponent<Player>() != (Object)(object)Player.m_localPlayer)
					{
						Plugin.Log.LogDebug((object)$"[MP] {((Object)z).name} plays {text3} {Time.time - st.StartedAt:0.00} s after its trigger");
					}
					if ((Object)(object)((Component)z).GetComponent<Player>() == (Object)(object)Player.m_localPlayer)
					{
						LastOwnClip = text3;
					}
				}
				if (text == st.Clip || text2 == st.Clip)
				{
					st.AbsentSince = -1f;
					st.LastActive = Time.time;
					st.Exiting = text == st.Clip && text2 != null && text2 != st.Clip;
					return;
				}
				if (st.AbsentSince < 0f)
				{
					st.AbsentSince = Time.time;
				}
				if (Time.time - st.AbsentSince >= 0.15f)
				{
					End(st);
				}
			}
		}

		private static void End(ComboState st)
		{
			st.Running = false;
			st.Exiting = false;
			st.EndedAt = Time.time;
		}

		private static void Preload(ZSyncAnimation z, ComboState st)
		{
			Humanoid component = ((Component)z).GetComponent<Humanoid>();
			if ((Object)(object)component == (Object)null || (Object)(object)component != (Object)(object)Player.m_localPlayer || Refs.AnimatorOf == null || ((Object)(object)st != (Object)null && (st.Running || Time.time < st.LastActive + 0.3f || Time.time < st.NextPreload)))
			{
				return;
			}
			if ((Object)(object)st == (Object)null)
			{
				st = ComboState.Of((Component)(object)z);
			}
			st.NextPreload = Time.time + 0.25f;
			Animator val = Refs.AnimatorOf.Invoke(z);
			if (!((Object)(object)val == (Object)null))
			{
				SetKey? setKey = OffHand.KeyOf(component);
				if (!Nullable.Equals(setKey, st.Preloaded) || (setKey.HasValue && !ClipSets.OursPresent(val, setKey.Value)))
				{
					ClipSets.Apply(val, setKey);
					st.Preloaded = setKey;
				}
			}
		}

		internal static void EquipPrefix(Humanoid __instance, ItemData item)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || item == null || !item.IsWeapon() || FamilyItems.FamilyOf(item).HasValue)
			{
				return;
			}
			ZSyncAnimation component = ((Component)__instance).GetComponent<ZSyncAnimation>();
			Animator val = (((Object)(object)component != (Object)null && Refs.AnimatorOf != null) ? Refs.AnimatorOf.Invoke(component) : null);
			if (!((Object)(object)val == (Object)null))
			{
				ClipSets.Apply(val, null);
				ComboState component2 = ((Component)component).GetComponent<ComboState>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.Preloaded = null;
				}
			}
		}

		private static void ClearStale(ZSyncAnimation z, ComboState st)
		{
			if ((Object)(object)((Component)z).GetComponent<Player>() == (Object)(object)Player.m_localPlayer)
			{
				st.Pending.Clear();
				st.PendingCombo.Clear();
				return;
			}
			Animator val = ((Refs.AnimatorOf != null) ? Refs.AnimatorOf.Invoke(z) : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			scratch.Clear();
			bool? flag = null;
			foreach (KeyValuePair<string, float> item in st.Pending)
			{
				if (!val.GetBool(item.Key))
				{
					scratch.Add(item.Key);
					continue;
				}
				if (!flag.HasValue)
				{
					flag = OwnClipPlaying(val, st);
				}
				if (TriggerHygiene.IsStale(Time.time - item.Value, flag.Value))
				{
					val.ResetTrigger(item.Key);
					scratch.Add(item.Key);
					Plugin.Log.LogDebug((object)$"[MP] stale trigger '{item.Key}' cleared on {((Object)z).name} after {Time.time - item.Value:0.00} s");
				}
			}
			foreach (string item2 in scratch)
			{
				st.Pending.Remove(item2);
				st.PendingCombo.Remove(item2);
			}
		}

		private static void ClearOrphans(ZSyncAnimation z, Animator anim, ComboState st)
		{
			if (st.PendingCombo.Count == 0)
			{
				return;
			}
			scratch.Clear();
			foreach (KeyValuePair<string, int> item in st.PendingCombo)
			{
				if (TriggerHygiene.IsOrphan(item.Value, st.ComboId, newFirstMoveOnScreen: true))
				{
					scratch.Add(item.Key);
				}
			}
			foreach (string item2 in scratch)
			{
				anim.ResetTrigger(item2);
				st.Pending.Remove(item2);
				st.PendingCombo.Remove(item2);
				Plugin.Log.LogDebug((object)("[MP] orphan trigger '" + item2 + "' from an older combo cleared on " + ((Object)z).name));
			}
		}

		internal static bool OwnClipPlaying(Animator anim, ComboState st)
		{
			string current = TopClip(anim.GetCurrentAnimatorClipInfo(0));
			string next = (anim.IsInTransition(0) ? TopClip(anim.GetNextAnimatorClipInfo(0)) : null);
			if (!IsOwn(st.Key, current, next))
			{
				SetKey? prevKey = st.PrevKey;
				if (prevKey.HasValue)
				{
					SetKey valueOrDefault = prevKey.GetValueOrDefault();
					return IsOwn(valueOrDefault, current, next);
				}
				return false;
			}
			return true;
		}

		private static bool IsOwn(SetKey key, string current, string next)
		{
			if (!ClipSets.IsOwnClip(key, current))
			{
				return ClipSets.IsOwnClip(key, next);
			}
			return true;
		}

		private static string TopClip(AnimatorClipInfo[] infos)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			AnimationClip val = null;
			float num = -1f;
			for (int i = 0; i < infos.Length; i++)
			{
				AnimatorClipInfo val2 = infos[i];
				if ((Object)(object)((AnimatorClipInfo)(ref val2)).clip != (Object)null && ((AnimatorClipInfo)(ref val2)).weight > num)
				{
					val = ((AnimatorClipInfo)(ref val2)).clip;
					num = ((AnimatorClipInfo)(ref val2)).weight;
				}
			}
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Object)val).name;
		}
	}
	internal class KnifeEvents : MonoBehaviour
	{
		private Character owner;

		internal const float DashFrom = 0.16f;

		internal const float DashTo = 17f / 30f;

		internal const float TargetRange = 3.5f;

		internal const float TargetHalfAngle = 60f;

		internal const float PassableRadius = 1f;

		private Character dashTarget;

		private Vector3 dashStart;

		private Vector3 dashCtrl;

		private Vector3 dashEnd;

		private float dashT0 = -1f;

		private readonly bool[] hiddenSide = new bool[2];

		private Animator animator;

		private readonly List<AnimatorClipInfo> s1Infos = new List<AnimatorClipInfo>(2);

		private Character Owner
		{
			get
			{
				if (!((Object)(object)owner != (Object)null))
				{
					return owner = ((Component)this).GetComponentInParent<Character>();
				}
				return owner;
			}
		}

		internal static void PlayerAwakePostfix(Player __instance)
		{
			Animator val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInChildren<Animator>() : null);
			if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent<KnifeEvents>() == (Object)null)
			{
				((Component)val).gameObject.AddComponent<KnifeEvents>();
			}
			ShadowStep.Attach(val);
			TwinPuppets.Attach_(val);
		}

		internal static void BeginShadowPassage(Player p)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_00d2: 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_00d6: 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_00dd: 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)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			Animator val = (((Object)(object)p != (Object)null) ? ((Component)p).GetComponentInChildren<Animator>() : null);
			KnifeEvents knifeEvents = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<KnifeEvents>() : null);
			if ((Object)(object)knifeEvents == (Object)null)
			{
				return;
			}
			knifeEvents.dashTarget = FindTarget((Character)(object)p, 3.5f, 60f);
			knifeEvents.dashT0 = -1f;
			if ((Object)(object)knifeEvents.dashTarget == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)p).transform.position;
			Vector3 position2 = ((Component)knifeEvents.dashTarget).transform.position;
			Vector3 val2 = Flat(position2 - position);
			if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
			{
				knifeEvents.dashTarget = null;
				return;
			}
			((Vector3)(ref val2)).Normalize();
			float radius = knifeEvents.dashTarget.GetRadius();
			if (radius > 1f)
			{
				knifeEvents.dashTarget = null;
				return;
			}
			Vector3 val3 = Vector3.Cross(Vector3.up, val2);
			knifeEvents.dashStart = position;
			knifeEvents.dashCtrl = position2 + val3 * (radius + 0.9f);
			knifeEvents.dashEnd = position2 + val2 * (radius + 0.9f) + val3 * 0.2f;
			knifeEvents.dashCtrl.y = (knifeEvents.dashEnd.y = position.y);
			knifeEvents.dashT0 = Time.time;
			((MonoBehaviour)knifeEvents).StartCoroutine(IgnoreCollisions((Character)(object)p, knifeEvents.dashTarget, 13f / 15f));
		}

		internal static void AddRootMotionPrefix(Character __instance, ref Vector3 vel)
		{
			//IL_0090: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00d1: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			Animator componentInChildren = ((Component)val).GetComponentInChildren<Animator>();
			KnifeEvents knifeEvents = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).GetComponent<KnifeEvents>() : null);
			if (!((Object)(object)knifeEvents == (Object)null) && !(knifeEvents.dashT0 < 0f) && !((Object)(object)knifeEvents.dashTarget == (Object)null))
			{
				float num = Time.time - knifeEvents.dashT0;
				if (!(num < 0.16f) && !(num > 44f / 75f))
				{
					float t = Mathf.Clamp01((num + Time.deltaTime - 0.16f) / (61f / 150f));
					Vector3 val2 = Flat(Bezier(knifeEvents.dashStart, knifeEvents.dashCtrl, knifeEvents.dashEnd, t) - ((Component)val).transform.position);
					float num2 = Mathf.Max(Time.deltaTime, 0.005f);
					vel = val2 / num2 / 55f;
				}
			}
		}

		public void KnifeTurn(string args)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
			Character val = Owner;
			Character val2 = dashTarget;
			dashTarget = null;
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || val.IsDead() || val2.IsDead())
			{
				return;
			}
			ZNetView component = ((Component)val).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner())
			{
				return;
			}
			Vector3 val3 = Flat(((Component)val2).transform.position - ((Component)val).transform.position);
			if (!(((Vector3)(ref val3)).sqrMagnitude < 0.0001f))
			{
				Quaternion val4 = Quaternion.LookRotation(((Vector3)(ref val3)).normalized);
				((Component)val).transform.rotation = val4;
				val.SetLookDir(val4 * Vector3.forward, 0f);
				Player val5 = (Player)(object)((val is Player) ? val : null);
				if (val5 != null && Refs.LookYaw != null)
				{
					Refs.LookYaw.Invoke(val5) = val4;
				}
			}
		}

		private static Vector3 Bezier(Vector3 a, Vector3 b, Vector3 c, float t)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0028: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f - t;
			return num * num * a + 2f * num * t * b + t * t * c;
		}

		private static Character FindTarget(Character c, float range, float halfAngle)
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0071: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			Character result = null;
			float num = float.MaxValue;
			Vector3 val = Flat(((Component)c).transform.forward);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)c) && !allCharacter.IsDead() && !allCharacter.IsPlayer() && !allCharacter.IsTamed())
				{
					Vector3 val2 = Flat(((Component)allCharacter).transform.position - ((Component)c).transform.position);
					float magnitude = ((Vector3)(ref val2)).magnitude;
					if (!(magnitude > range + allCharacter.GetRadius()) && !(magnitude < 0.01f) && !(Vector3.Angle(normalized, val2) > halfAngle) && magnitude < num)
					{
						num = magnitude;
						result = allCharacter;
					}
				}
			}
			return result;
		}

		private static IEnumerator IgnoreCollisions(Character c, Character t, float seconds)
		{
			Collider[] mine = ((Component)c).GetComponentsInChildren<Collider>();
			Collider[] theirs = ((Component)t).GetComponentsInChildren<Collider>();
			SetIgnore(mine, theirs, ignore: true);
			yield return (object)new WaitForSeconds(seconds);
			SetIgnore(mine, theirs, ignore: false);
		}

		private static void SetIgnore(Collider[] a, Collider[] b, bool ignore)
		{
			foreach (Collider val in a)
			{
				foreach (Collider val2 in b)
				{
					if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
					{
						Physics.IgnoreCollision(val, val2, ignore);
					}
				}
			}
		}

		private static Vector3 Flat(Vector3 v)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			v.y = 0f;
			return v;
		}

		public void KnifeToss(string side)
		{
		}

		public void KnifeCatch(string side)
		{
		}

		public void ThrowRelease(string side)
		{
			Character obj = Owner;
			KnifeThrow.Release((Player)(object)((obj is Player) ? obj : null), side ?? "");
		}

		private void LateUpdate()
		{
			Character val = Owner;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			for (int i = 0; i < 2; i++)
			{
				bool flag = KnifeThrow.InFlight(val, i);
				if (!flag && !hiddenSide[i])
				{
					continue;
				}
				GameObject val2 = KnifeThrow.HeldVisual(val, i);
				if ((Object)(object)val2 == (Object)null)
				{
					hiddenSide[i] = false;
					continue;
				}
				Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>(true);
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					componentsInChildren[j].forceRenderingOff = flag;
				}
				hiddenSide[i] = flag;
			}
		}

		private void Update()
		{
			FaceCameraDuringThrow();
		}

		private void FaceCameraDuringThrow()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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)
			Character obj = Owner;
			Player val = (Player)(object)((obj is Player) ? obj : null);
			if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer || (Object)(object)GameCamera.instance == (Object)null)
			{
				return;
			}
			if ((Object)(object)animator == (Object)null)
			{
				animator = ((Component)this).GetComponent<Animator>();
			}
			if ((Object)(object)animator == (Object)null || !PlayingS1())
			{
				return;
			}
			Vector3 val2 = Flat(((Component)GameCamera.instance).transform.forward);
			if (!(((Vector3)(ref val2)).sqrMagnitude < 0.0001f))
			{
				Quaternion val3 = Quaternion.LookRotation(((Vector3)(ref val2)).normalized);
				((Component)val).transform.rotation = val3;
				((Character)val).SetLookDir(((Vector3)(ref val2)).normalized, 0f);
				if (Refs.LookYaw != null)
				{
					Refs.LookYaw.Invoke(val) = val3;
				}
			}
		}

		private bool PlayingS1()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			animator.GetCurrentAnimatorClipInfo(0, s1Infos);
			foreach (AnimatorClipInfo s1Info in s1Infos)
			{
				AnimatorClipInfo current = s1Info;
				if ((Object)(object)((AnimatorClipInfo)(ref current)).clip != (Object)null && ((AnimatorClipInfo)(ref current)).weight > 0.5f && Families.ParseClip(((Object)((AnimatorClipInfo)(ref current)).clip).name, out var move) && move == Move.S1)
				{
					return true;
				}
			}
			return false;
		}

		public void VeilVanish(string args)
		{
		}
	}
	internal static class KnifeFx
	{
		internal struct Spec
		{
			public string Texture;

			public bool Additive;

			public bool World;

			public float Rate;

			public int Burst;

			public float LifeMin;

			public float LifeMax;

			public float SpeedMin;

			public float SpeedMax;

			public float SizeMin;

			public float SizeMax;

			public float SizeEnd;

			public float Radius;

			public Color ColorA;

			public Color ColorB;

			public float Gravity;
		}

		private static bool tried;

		private static Material alpha;

		private static Material additive;

		private static readonly Dictionary<string, Material> mats = new Dictionary<string, Material>();

		internal static bool Ready
		{
			get
			{
				if (!tried)
				{
					tried = true;
					alpha = ClipSets.ReadAsset<Material>("Assets/KnifeFx/Materials/KfxAlpha.mat");
					additive = ClipSets.ReadAsset<Material>("Assets/KnifeFx/Materials/KfxAdditive.mat");
					if ((Object)(object)alpha == (Object)null || (Object)(object)additive == (Object)null)
					{
						Plugin.Log.LogWarning((object)"Knife VFX materials are not in the bundle - effects are off.");
					}
				}
				if ((Object)(object)alpha != (Object)null)
				{
					return (Object)(object)additive != (Object)null;
				}
				return false;
			}
		}

		internal static Material Mat(string texture, bool add)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			if (!Ready)
			{
				return null;
			}
			string text = texture + (add ? "|a" : "|b");
			if (mats.TryGetValue(text, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			value = new Material(add ? additive : alpha)
			{
				name = "KnifeFx_" + text
			};
			Texture2D val = ClipSets.ReadAsset<Texture2D>("Assets/KnifeFx/Textures/" + texture + ".png");
			if ((Object)(object)val != (Object)null)
			{
				value.mainTexture = (Texture)(object)val;
			}
			mats[text] = value;
			return value;
		}

		internal static ParticleSystem Layer(GameObject root, Spec s)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: 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_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: 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_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Expected O, but got Unknown
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: 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_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("kfx_" + s.Texture);
			val.transform.SetParent(root.transform, false);
			val.SetActive(false);
			ParticleSystem val2 = val.AddComponent<ParticleSystem>();
			val2.Stop(true, (ParticleSystemStopBehavior)0);
			ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>();
			((Renderer)component).sharedMaterial = Mat(s.Texture, s.Additive);
			component.renderMode = (ParticleSystemRenderMode)0;
			component.sortingFudge = (s.Additive ? (-2f) : 0f);
			MainModule main = val2.main;
			((MainModule)(ref main)).playOnAwake = false;
			((MainModule)(ref main)).loop = true;
			((MainModule)(ref main)).duration = 1f;
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(s.LifeMin, s.LifeMax);
			((MainModule)(ref main)).startSpeed = new MinMaxCurve(s.SpeedMin, s.SpeedMax);
			((MainModule)(ref main)).startSize = new MinMaxCurve(s.SizeMin, s.SizeMax);
			((MainModule)(ref main)).startRotation = new MinMaxCurve(0f, MathF.PI * 2f);
			((MainModule)(ref main)).startColor = new MinMaxGradient(s.ColorA, s.ColorB);
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(s.Gravity);
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)(s.World ? 1 : 0);
			((MainModule)(ref main)).maxParticles = Mathf.Max(16, s.Burst + Mathf.CeilToInt(s.Rate * s.LifeMax) + 8);
			EmissionModule emission = val2.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(s.Rate);
			((EmissionModule)(ref emission)).SetBursts((Burst[])(object)((s.Burst <= 0) ? new Burst[0] : new Burst[1]
			{
				new Burst(0f, (short)s.Burst)
			}));
			ShapeModule shape = val2.shape;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0;
			((ShapeModule)(ref shape)).radius = Mathf.Max(0.01f, s.Radius);
			ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			Gradient val3 = new Gradient();
			val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
			{
				new GradientColorKey(Color.white, 0f),
				new GradientColorKey(Color.white, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[4]
			{
				new GradientAlphaKey(0f, 0f),
				new GradientAlphaKey(1f, 0.12f),
				new GradientAlphaKey(0.7f, 0.5f),
				new GradientAlphaKey(0f, 1f)
			});
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val3);
			if (s.SizeEnd > 0f)
			{
				SizeOverLifetimeModule sizeOverLifetime = val2.sizeOverLifetime;
				((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true;
				((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, AnimationCurve.Linear(0f, 1f, 1f, s.SizeEnd));
			}
			val.SetActive(true);
			return val2;
		}

		internal static TrailRenderer Trail(GameObject root, string texture, float time, float width, Color color)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("kfx_trail");
			val.transform.SetParent(root.transform, false);
			TrailRenderer val2 = val.AddComponent<TrailRenderer>();
			((Renderer)val2).sharedMaterial = Mat(texture, add: false);
			val2.time = time;
			val2.minVertexDistance = 0.05f;
			val2.textureMode = (LineTextureMode)0;
			val2.alignment = (LineAlignment)0;
			val2.widthCurve = AnimationCurve.Linear(0f, width, 1f, 0f);
			Gradient val3 = new Gradient();
			val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
			{
				new GradientColorKey(color, 0f),
				new GradientColorKey(color, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[2]
			{
				new GradientAlphaKey(color.a, 0f),
				new GradientAlphaKey(0f, 1f)
			});
			val2.colorGradient = val3;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			return val2;
		}
	}
	internal class KnifeGrip : MonoBehaviour
	{
		internal enum Grip
		{
			Vanilla,
			Fwd,
			Rev,
			RevIn,
			FwdIn
		}

		private struct Key
		{
			public float T0;

			public float T1;

			public Grip To;

			public Key(float t0, float t1, Grip to)
			{
				T0 = t0;
				T1 = t1;
				To = to;
			}
		}

		private static readonly Quaternion Mount = new Quaternion(-0.5f, -0.5f, 0.5f, 0.5f);

		private static readonly Quaternion GFwd = new Quaternion(0.0946f, -0.6402f, -0.7558f, 0.1f);

		private static readonly Quaternion GRev = new Quaternion(-0.0721f, 0.5644f, -0.814f, 0.1172f);

		private static readonly Quaternion GFwdIn = new Quaternion(-0.898f, 0.0791f, -0.1245f, 0.4146f);

		private static readonly Quaternion GRevIn = new Quaternion(0.7558f, 0.1f, 0.0946f, 0.6402f);

		private static readonly Vector3 PFwd = new Vector3(-0.0218f, -0.0285f, -0.0048f);

		private static readonly Vector3 PRev = new Vector3(-0.0375f, 0.027f, -0.0105f);

		private static readonly Vector3 PRevIn = new Vector3(-0.0381f, 0.0285f, 0.0049f);

		internal const float EaseIn = 0.08f;

		internal const float EaseOut = 0.15f;

		private static readonly Dictionary<Move, Key[]> Keys = new Dictionary<Move, Key[]>
		{
			{
				Move.L1,
				new Key[1]
				{
					new Key(0f, 0.08f, Grip.Fwd)
				}
			},
			{
				Move.L2,
				new Key[2]
				{
					new Key(0f, 0.08f, Grip.Fwd),
					new Key(0.09f, 0.24f, Grip.Rev)
				}
			},
			{
				Move.L3,
				new Key[1]
				{
					new Key(0.03f, 0.15f, Grip.Fwd)
				}
			},
			{
				Move.S1,
				new Key[1]
				{
					new Key(0f, 0.08f, Grip.Fwd)
				}
			},
			{
				Move.S2,
				new Key[1]
				{
					new Key(0f, 0.12f, Grip.Rev)
				}
			},
			{
				Move.S3,
				new Key[1]
				{
					new Key(0f, 0.12f, Grip.Fwd)
				}
			},
			{
				Move.H2,
				new Key[1]
				{
					new Key(0f, 0.14f, Grip.FwdIn)
				}
			},
			{
				Move.H3,
				new Key[1]
				{
					new Key(0.04f, 0.2f, Grip.Fwd)
				}
			}
		};

		private Animator anim;

		private VisEquipment vis;

		private Transform hand;

		private Transform item;

		private Quaternion shown = Quaternion.identity;

		private Quaternion carried = Quaternion.identity;

		private Vector3 shownPos;

		private Vector3 carriedPos;

		private string lastClip;

		private float outSince = -1f;

		private static readonly Vector3 Attach = new Vector3(0f, 0.0997f, 0.0284f);

		internal const float ReturnSpan = 0.25f;

		private Quaternion vanillaLocal;

		private Vector3 vanillaLocalPos;

		private Transform vanillaOf;

		private readonly List<AnimatorClipInfo> infos = new List<AnimatorClipInfo>(2);

		private static Vector3 Offset(Grip g)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			switch (g)
			{
			default:
				return Vector3.zero;
			case Grip.RevIn:
				return PRevIn;
			case Grip.Rev:
				return PRev;
			case Grip.Fwd:
			case Grip.FwdIn:
				return PFwd;
			}
		}

		private static Quaternion Delta(Grip g)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_002f: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			return (Quaternion)(g switch
			{
				Grip.Fwd => GFwd * Quaternion.Inverse(Mount), 
				Grip.Rev => GRev * Quaternion.Inverse(Mount), 
				Grip.RevIn => GRevIn * Quaternion.Inverse(Mount), 
				Grip.FwdIn => GFwdIn * Quaternion.Inverse(Mount), 
				_ => Quaternion.identity, 
			});
		}

		internal static Quaternion At(Move m, float t, Quaternion from, Vector3 fromPos, out Vector3 pos, float len)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: 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_000b: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = At(m, t, from, fromPos, out pos);
			if (len <= 0f || m == Move.S1 || m == Move.H1 || m == Move.None)
			{
				return val;
			}
			float num = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01((t - (len - 0.25f)) / 0.25f));
			pos = Vector3.Lerp(pos, Vector3.zero, num);
			return Quaternion.Slerp(val, Quaternion.identity, num);
		}

		internal static Quaternion At(Move m, float t, Quaternion from, Vector3 fromPos, out Vector3 pos)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0024: 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_002e: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_00e1: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			if (m == Move.S1 && t >= 0.26667f)
			{
				KnifeTossPath.At(KnifeTossPath.Right, t - 0.26667f, out var pos2, out var rot);
				pos = pos2 - Attach;
				return rot * Quaternion.Inverse(Mount);
			}
			pos = fromPos;
			if (!Keys.TryGetValue(m, out var value))
			{
				return from;
			}
			Quaternion val = from;
			Key[] array = value;
			for (int i = 0; i < array.Length; i++)
			{
				Key key = array[i];
				if (t <= key.T0)
				{
					break;
				}
				float num = Mathf.SmoothStep(0f, 1f, (key.T1 > key.T0) ? Mathf.Clamp01((t - key.T0) / (key.T1 - key.T0)) : 1f);
				val = Quaternion.Slerp(val, Delta(key.To), num);
				pos = Vector3.Lerp(pos, Offset(key.To), num);
			}
			return val;
		}

		private void LateUpdate()
		{
			//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_0117: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: 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_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_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: 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)
			//IL_0199: 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_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: 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_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)anim == (Object)null)
			{
				ZSyncAnimation component = ((Component)this).GetComponent<ZSyncAnimation>();
				anim = (((Object)(object)component != (Object)null && Refs.AnimatorOf != null) ? Refs.AnimatorOf.Invoke(component) : null);
				if ((Object)(object)anim == (Object)null || !anim.isHuman)
				{
					return;
				}
				hand = anim.GetBoneTransform((HumanBodyBones)18);
			}
			if ((Object)(object)vis == (Object)null)
			{
				vis = ((Component)this).GetComponent<VisEquipment>();
			}
			if ((Object)(object)vis == (Object)null || (Object)(object)hand == (Object)null || Refs.RightItemInstance == null)
			{
				return;
			}
			GameObject val = Refs.RightItemInstance.Invoke(vis);
			if ((Object)(object)val != (Object)null)
			{
				Humanoid component2 = ((Component)this).GetComponent<Humanoid>();
				if (FamilyItems.FamilyOf((component2 != null) ? component2.GetCurrentWeapon() : null) == Family.Twin)
				{
					val = null;
				}
			}
			item = (Object.op_Implicit((Object)(object)val) ? val.transform : null);
			if ((Object)(object)item == (Object)null)
			{
				shown = (carried = Quaternion.identity);
				shownPos = (carriedPos = Vector3.zero);
				lastClip = null;
				return;
			}
			Quaternion val2;
			Vector3 pos;
			if (OwnClip(out var name, out var move, out var time, out var len))
			{
				if (name != lastClip)
				{
					carried = shown;
					carriedPos = shownPos;
					lastClip = name;
				}
				val2 = At(move, time, carried, carriedPos, out pos, len);
				outSince = -1f;
			}
			else
			{
				if (lastClip != null)
				{
					carried = shown;
					carriedPos = shownPos;
					lastClip = null;
					outSince = Time.time;
				}
				if (outSince < 0f)
				{
					return;
				}
				float num = Mathf.Clamp01((Time.time - outSince) / 0.15f);
				float num2 = Mathf.SmoothStep(0f, 1f, num);
				val2 = Quaternion.Slerp(carried, Quaternion.identity, num2);
				pos = Vector3.Lerp(carriedPos, Vector3.zero, num2);
				if (num >= 1f)
				{
					outSince = -1f;
				}
			}
			shown = val2;
			shownPos = pos;
			Quaternion val3 = (((Object)(object)item.parent != (Object)null) ? (item.parent.rotation * VanillaLocal()) : item.rotation);
			Quaternion rotation = hand.rotation;
			item.rotation = rotation * val2 * Quaternion.Inverse(rotation) * val3;
			if ((Object)(object)item.parent != (Object)null)
			{
				item.position = item.parent.TransformPoint(VanillaLocalPos()) + rotation * pos;
			}
		}

		private Quaternion VanillaLocal()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)vanillaOf != (Object)(object)item)
			{
				vanillaOf = item;
				vanillaLocal = item.localRotation;
				vanillaLocalPos = item.localPosition;
			}
			return vanillaLocal;
		}

		private Vector3 VanillaLocalPos()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			VanillaLocal();
			return vanillaLocalPos;
		}

		private bool OwnClip(out string name, out Move move, out float time, out float len)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			name = null;
			move = Move.None;
			time = 0f;
			len = 0f;
			float best = 0f;
			Probe(anim.GetCurrentAnimatorStateInfo(0), next: false, ref name, ref move, ref time, ref best, ref len);
			if (anim.IsInTransition(0))
			{
				Probe(anim.GetNextAnimatorStateInfo(0), next: true, ref name, ref move, ref time, ref best, ref len);
			}
			return name != null;
		}

		private void Probe(AnimatorStateInfo state, bool next, ref string name, ref Move move, ref float time, ref float best, ref float len)
		{
			//IL_0039: 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)
			if (next)
			{
				anim.GetNextAnimatorClipInfo(0, infos);
			}
			else
			{
				anim.GetCurrentAnimatorClipInfo(0, infos);
			}
			foreach (AnimatorClipInfo info in infos)
			{
				AnimatorClipInfo current = info;
				if (!((Object)(object)((AnimatorClipInfo)(ref current)).clip == (Object)null) && !(((AnimatorClipInfo)(ref current)).weight <= best) && Families.ParseClip(((Object)((AnimatorClipInfo)(ref current)).clip).name, out var move2))
				{
					best = ((AnimatorClipInfo)(ref current)).weight;
					name = ((Object)((AnimatorClipInfo)(ref current)).clip).name;
					move = move2;
					time = Mathf.Clamp01(((AnimatorStateInfo)(ref state)).normalizedTime) * ((AnimatorClipInfo)(ref current)).clip.length;
					len = ((AnimatorClipInfo)(ref current)).clip.length;
				}
			}
		}

		private void OnDisable()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)item != (Object)null && (Object)(object)item.parent != (Object)null && (Object)(object)vanillaOf == (Object)(object)item)
			{
				item.localRotation = vanillaLocal;
				item.localPosition = vanillaLocalPos;
			}
		}
	}
	internal static class KnifeThrow
	{
		internal const float Speed = 28f;

		internal const float GravityScale = 0.65f;

		internal const float Timeout = 10f;

		internal const float SpinDegPerSec = 820f;

		internal const float ReturnSeconds = 0.35f;

		internal const float Radius = 0.12f;

		internal const float OwnerIgnoreSeconds = 0.08f;

		internal const float AimRange = 40f;

		private const string RpcLaunch = "ComboKnife_Throw";

		private static bool registered;

		private static readonly Dictionary<ZDOID, bool[]> inFlight = new Dictionary<ZDOID, bool[]>();

		internal const float PointBlank = 1.5f;

		internal const float ThrowWear = 3f;

		internal static bool AnyInFlight(Character c)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c != (Object)null && inFlight.TryGetValue(c.GetZDOID(), out var value))
			{
				if (!value[0])
				{
					return value[1];
				}
				return true;
			}
			return false;
		}

		internal static bool InFlight(Character c, int side)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c != (Object)null && inFlight.TryGetValue(c.GetZDOID(), out var value))
			{
				return value[side];
			}
			return false;
		}

		internal static void Register()
		{
			if (!registered && ZRoutedRpc.instance != null)
			{
				registered = true;
				ZRoutedRpc.instance.Register<ZDOID, Vector3, Vector3, int>("ComboKnife_Throw", (Method<ZDOID, Vector3, Vector3, int>)OnLaunch);
			}
		}

		internal static void GameStartPostfix()
		{
			registered = false;
			inFlight.Clear();
			Register();
		}

		internal static void Release(Player p, string side)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00f3: 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_00ca: 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)
			if ((Object)(object)p == (Object)null || (Object)(object)p != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			Register();
			int num = ((side == "left") ? 1 : 0);
			if (!InFlight((Character)(object)p, num))
			{
				Animator componentInChildren = ((Component)p).GetComponentInChildren<Animator>();
				Transform val = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.GetBoneTransform((HumanBodyBones)((num == 1) ? 17 : 18)) : null);
				Vector3 val2 = (((Object)(object)val != (Object)null) ? val.position : (((Component)p).transform.position + Vector3.up * 1.4f));
				Vector3 val3 = AimDirection(p, val2);
				if (num == 0)
				{
					WearForThrow(((Humanoid)p).GetCurrentWeapon());
				}
				if (ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(0L, "ComboKnife_Throw", new object[4]
					{
						((Character)p).GetZDOID(),
						val2,
						val3,
						num
					});
				}
				else
				{
					OnLaunch(0L, ((Character)p).GetZDOID(), val2, val3, num);
				}
			}
		}

		private static Vector3 AimDirection(Player p, Vector3 origin)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_00db: 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_00e1: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_0152: Unknown result type (might be due to invalid IL or missing references)
			Camera val = (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).GetComponent<Camera>() : null);
			RaycastHit val3 = default(RaycastHit);
			Vector3 val2 = ((!((Object)(object)val != (Object)null) || !Physics.Raycast(((Component)val).transform.position, ((Component)val).transform.forward, ref val3, 40f, HitMask(), (QueryTriggerInteraction)1) || !((Object)(object)((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<Player>() != (Object)(object)p)) ? (((Object)(object)val != (Object)null) ? (((Component)val).transform.position + ((Component)val).transform.forward * 25f) : (origin + ((Component)p).transform.forward * 25f)) : ((RaycastHit)(ref val3)).point);
			Vector3 val4 = (((Object)(object)val != (Object)null) ? ((Component)val).transform.forward : ((Component)p).transform.forward);
			Vector3 val5 = val2 - origin;
			if (((Vector3)(ref val5)).magnitude < 1.5f || Vector3.Dot(((Vector3)(ref val5)).normalized, val4) < 0.5f)
			{
				return ((Vector3)(ref val4)).normalized;
			}
			float num = ((Vector3)(ref val5)).magnitude / 28f;
			ref float y = ref val2.y;
			float num2 = y;
			Vector3 val6 = Physics.gravity;
			y = num2 + 0.5f * ((Vector3)(ref val6)).magnitude * 0.65f * num * num;
			val6 = val2 - origin;
			return ((Vector3)(ref val6)).normalized;
		}

		internal static void HitSound(Character thrower, bool struckSomething, Vector3 point)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			Character obj = ((thrower is Hu