Decompiled source of HarpoonAnimFix v1.0.1

HarpoonAnimFix.dll

Decompiled 15 hours ago
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using EntityStates;
using EntityStates.Engi.EngiMissilePainter;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;

[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("HarpoonAnimFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("HarpoonAnimFix")]
[assembly: AssemblyTitle("HarpoonAnimFix")]
[assembly: AssemblyVersion("1.0.1.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 HarpoonAnimFix
{
	internal enum TrackKind : byte
	{
		Position,
		Euler,
		Scale
	}
	internal sealed class Channel
	{
		private readonly float constant;

		private readonly float[] times;

		private readonly float[] coeffs;

		internal Channel(float constant, float[] times, float[] coeffs)
		{
			this.constant = constant;
			this.times = times;
			this.coeffs = coeffs;
		}

		internal float Evaluate(float t)
		{
			if (times == null)
			{
				return constant;
			}
			int num = 0;
			int num2 = times.Length - 1;
			while (num < num2)
			{
				int num3 = num + num2 + 1 >> 1;
				if (times[num3] <= t)
				{
					num = num3;
				}
				else
				{
					num2 = num3 - 1;
				}
			}
			float num4 = t - times[num];
			int num5 = num * 4;
			return ((coeffs[num5] * num4 + coeffs[num5 + 1]) * num4 + coeffs[num5 + 2]) * num4 + coeffs[num5 + 3];
		}
	}
	internal sealed class Track
	{
		internal readonly int Bone;

		internal readonly TrackKind Kind;

		internal readonly Vector3 Reference;

		internal readonly Quaternion InverseReferenceRotation;

		private readonly Channel x;

		private readonly Channel y;

		private readonly Channel z;

		internal Track(int bone, TrackKind kind, Vector3 reference, Channel x, Channel y, Channel z)
		{
			//IL_0015: 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_0027: 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_002d: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			Bone = bone;
			Kind = kind;
			Reference = reference;
			InverseReferenceRotation = ((kind == TrackKind.Euler) ? Quaternion.Inverse(Quaternion.Euler(reference)) : Quaternion.identity);
			this.x = x;
			this.y = y;
			this.z = z;
		}

		internal Vector3 Sample(float t)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(x.Evaluate(t), y.Evaluate(t), z.Evaluate(t));
		}
	}
	internal sealed class Clip
	{
		internal readonly float Length;

		internal readonly Track[] Tracks;

		internal Clip(float length, Track[] tracks)
		{
			Length = length;
			Tracks = tracks;
		}
	}
	internal static class OriginalClips
	{
		internal static readonly string[] BonePaths;

		internal static readonly Clip Prep;

		internal static readonly Clip Idle;

		internal static readonly Clip Exit;

		internal static readonly Clip FireLeft;

		internal static readonly Clip FireRight;

		static OriginalClips()
		{
			using Stream stream = typeof(OriginalClips).Assembly.GetManifestResourceStream("HarpoonAnimFix.Clips.bin");
			using DeflateStream input = new DeflateStream(stream, CompressionMode.Decompress);
			using BinaryReader binaryReader = new BinaryReader(input);
			BonePaths = new string[binaryReader.ReadByte()];
			for (int i = 0; i < BonePaths.Length; i++)
			{
				BonePaths[i] = Encoding.UTF8.GetString(binaryReader.ReadBytes(binaryReader.ReadByte()));
			}
			Clip[] array = new Clip[binaryReader.ReadByte()];
			for (int j = 0; j < array.Length; j++)
			{
				array[j] = ReadClip(binaryReader);
			}
			Prep = array[0];
			Idle = array[1];
			Exit = array[2];
			FireLeft = array[3];
			FireRight = array[4];
		}

		private static Clip ReadClip(BinaryReader reader)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			float length = reader.ReadSingle();
			Track[] array = new Track[reader.ReadByte()];
			Vector3 reference = default(Vector3);
			for (int i = 0; i < array.Length; i++)
			{
				int bone = reader.ReadByte();
				TrackKind kind = (TrackKind)reader.ReadByte();
				((Vector3)(ref reference))..ctor(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
				array[i] = new Track(bone, kind, reference, ReadChannel(reader), ReadChannel(reader), ReadChannel(reader));
			}
			return new Clip(length, array);
		}

		private static Channel ReadChannel(BinaryReader reader)
		{
			int num = reader.ReadByte();
			if (num == 0)
			{
				return new Channel(reader.ReadSingle(), null, null);
			}
			float[] array = new float[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = reader.ReadSingle();
			}
			float[] array2 = new float[num * 4];
			for (int j = 0; j < array2.Length; j++)
			{
				array2[j] = reader.ReadSingle();
			}
			return new Channel(0f, array, array2);
		}
	}
	[BepInPlugin("FluxSquido.HarpoonAnimFix", "HarpoonAnimFix", "1.0.1")]
	public sealed class HarpoonAnimFixPlugin : BaseUnityPlugin
	{
		public const string Guid = "FluxSquido.HarpoonAnimFix";

		public const string Name = "HarpoonAnimFix";

		public const string Version = "1.0.1";

		internal static ManualLogSource Log;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			harmony = new Harmony("FluxSquido.HarpoonAnimFix");
			harmony.PatchAll(typeof(Patches));
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
	[DefaultExecutionOrder(-1000)]
	internal sealed class HarpoonRig : MonoBehaviour
	{
		private struct Applied
		{
			public bool Valid;

			public Quaternion WrittenRotation;

			public Vector3 WrittenPosition;

			public Vector3 WrittenScale;

			public BonePose Delta;
		}

		private const float GestureCrossfade = 0.1f;

		private const float ExitSpeed = 0.6f;

		private const float LeftExitNormalized = 1f;

		private const float LeftExitSeconds = 0.1f;

		private const float RightExitNormalized = 17f / 32f;

		private const float RightExitSeconds = 0.25f;

		private static readonly int PrepHash = Animator.StringToHash("PrepHarpoons");

		private static readonly int IdleHash = Animator.StringToHash("IdleHarpoons");

		private static readonly int ExitHash = Animator.StringToHash("ExitHarpoons");

		private static readonly int FireGrenadeLeftHash = Animator.StringToHash("FireGrenadeLeft");

		private static readonly int FireGrenadeRightHash = Animator.StringToHash("FireGrenadeRight");

		private readonly LayerState gesture = new LayerState();

		private readonly LayerState leftCannon = new LayerState();

		private readonly LayerState rightCannon = new LayerState();

		private Animator animator;

		private int gestureLayer = -1;

		private int leftLayer = -1;

		private int rightLayer = -1;

		private Transform[] bones;

		private BonePose[] layerPose;

		private BonePose[] totalPose;

		private Applied[] applied;

		private bool anyApplied;

		internal static HarpoonRig For(Animator animator)
		{
			if (!Object.op_Implicit((Object)(object)animator))
			{
				return null;
			}
			HarpoonRig harpoonRig = ((Component)animator).GetComponent<HarpoonRig>();
			if (!Object.op_Implicit((Object)(object)harpoonRig))
			{
				harpoonRig = ((Component)animator).gameObject.AddComponent<HarpoonRig>();
				harpoonRig.Init(animator);
			}
			if (harpoonRig.bones == null)
			{
				return null;
			}
			return harpoonRig;
		}

		private void Init(Animator anim)
		{
			animator = anim;
			gestureLayer = anim.GetLayerIndex("Gesture, Additive");
			leftLayer = anim.GetLayerIndex("Gesture Left Cannon, Additive");
			rightLayer = anim.GetLayerIndex("Gesture Right Cannon, Additive");
			string[] bonePaths = OriginalClips.BonePaths;
			Transform[] array = (Transform[])(object)new Transform[bonePaths.Length];
			for (int i = 0; i < bonePaths.Length; i++)
			{
				array[i] = ((Component)anim).transform.Find(bonePaths[i]);
				if (!Object.op_Implicit((Object)(object)array[i]))
				{
					HarpoonAnimFixPlugin.Log.LogWarning((object)("'" + ((Object)anim).name + "' has no bone '" + bonePaths[i] + "'; harpoon animation disabled for this model."));
					((Behaviour)this).enabled = false;
					return;
				}
			}
			bones = array;
			layerPose = new BonePose[bonePaths.Length];
			totalPose = new BonePose[bonePaths.Length];
			applied = new Applied[bonePaths.Length];
		}

		internal void PaintEntered()
		{
			gesture.CrossFade(OriginalClips.Prep, 1f, 0.1f);
			((Behaviour)this).enabled = true;
		}

		internal void PaintExited()
		{
			gesture.CrossFade(OriginalClips.Exit, 0.6f, 0.1f);
			((Behaviour)this).enabled = true;
		}

		internal void FireEntered()
		{
			gesture.Play(OriginalClips.Idle, 1f);
			((Behaviour)this).enabled = true;
		}

		internal void FireExited()
		{
			gesture.CrossFade(OriginalClips.Exit, 0.6f, 0.1f);
			((Behaviour)this).enabled = true;
		}

		internal void Shot(bool left)
		{
			if (left)
			{
				leftCannon.Play(OriginalClips.FireLeft, 1f, 1f, 0.1f);
			}
			else
			{
				rightCannon.Play(OriginalClips.FireRight, 1f, 17f / 32f, 0.25f);
			}
			((Behaviour)this).enabled = true;
		}

		private void LateUpdate()
		{
			if (!Object.op_Implicit((Object)(object)animator) || !((Behaviour)animator).isActiveAndEnabled || (!gesture.Active && !leftCannon.Active && !rightCannon.Active))
			{
				if (anyApplied)
				{
					Restore();
				}
				((Behaviour)this).enabled = false;
				return;
			}
			float dt = Time.deltaTime * animator.speed;
			gesture.Advance(dt);
			leftCannon.Advance(dt);
			rightCannon.Advance(dt);
			FollowAnimator();
			for (int i = 0; i < totalPose.Length; i++)
			{
				totalPose[i] = BonePose.Identity;
			}
			ComposeLayer(gesture);
			ComposeLayer(leftCannon);
			ComposeLayer(rightCannon);
			Apply();
		}

		private void FollowAnimator()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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)
			gesture.Fade = 1f;
			if (gestureLayer >= 0 && gesture.Active)
			{
				AnimatorStateInfo val = animator.GetCurrentAnimatorStateInfo(gestureLayer);
				int shortNameHash = ((AnimatorStateInfo)(ref val)).shortNameHash;
				bool flag = animator.IsInTransition(gestureLayer);
				int num;
				if (!flag)
				{
					num = 0;
				}
				else
				{
					val = animator.GetNextAnimatorStateInfo(gestureLayer);
					num = ((AnimatorStateInfo)(ref val)).shortNameHash;
				}
				int hash = num;
				bool flag2 = IsGestureHarpoon(shortNameHash);
				bool flag3 = IsGestureHarpoon(hash);
				if (!flag2 && !flag3)
				{
					gesture.Stop();
				}
				else if (flag2 && flag && !flag3)
				{
					LayerState layerState = gesture;
					AnimatorTransitionInfo animatorTransitionInfo = animator.GetAnimatorTransitionInfo(gestureLayer);
					layerState.Fade = 1f - ((AnimatorTransitionInfo)(ref animatorTransitionInfo)).normalizedTime;
				}
			}
			if (leftLayer >= 0 && leftCannon.Active && LayerIs(leftLayer, FireGrenadeLeftHash))
			{
				leftCannon.Stop();
			}
			if (rightLayer >= 0 && rightCannon.Active && LayerIs(rightLayer, FireGrenadeRightHash))
			{
				rightCannon.Stop();
			}
		}

		private static bool IsGestureHarpoon(int hash)
		{
			if (hash != PrepHash && hash != IdleHash)
			{
				return hash == ExitHash;
			}
			return true;
		}

		private bool LayerIs(int layer, int hash)
		{
			//IL_0007: 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_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)
			AnimatorStateInfo val = animator.GetCurrentAnimatorStateInfo(layer);
			if (((AnimatorStateInfo)(ref val)).shortNameHash == hash)
			{
				return true;
			}
			if (animator.IsInTransition(layer))
			{
				val = animator.GetNextAnimatorStateInfo(layer);
				return ((AnimatorStateInfo)(ref val)).shortNameHash == hash;
			}
			return false;
		}

		private void ComposeLayer(LayerState layer)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0097: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			if (layer.Active)
			{
				for (int i = 0; i < layerPose.Length; i++)
				{
					layerPose[i] = BonePose.Empty;
				}
				layer.Accumulate(layerPose);
				for (int j = 0; j < layerPose.Length; j++)
				{
					BonePose bonePose = layerPose[j].Resolve();
					totalPose[j].Rotation = totalPose[j].Rotation * bonePose.Rotation;
					ref Vector3 position = ref totalPose[j].Position;
					position += bonePose.Position;
					totalPose[j].Scale = Vector3.Scale(totalPose[j].Scale, bonePose.Scale);
				}
			}
		}

		private void Apply()
		{
			//IL_001e: 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_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)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_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_00d3: 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)
			//IL_00e3: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_005d: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0086: 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_0096: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < bones.Length; i++)
			{
				Transform val = bones[i];
				ref Applied reference = ref applied[i];
				Quaternion val2 = val.localRotation;
				Vector3 val3 = val.localPosition;
				Vector3 val4 = val.localScale;
				if (reference.Valid && ((Quaternion)(ref val2)).Equals(reference.WrittenRotation) && ((Vector3)(ref val3)).Equals(reference.WrittenPosition) && ((Vector3)(ref val4)).Equals(reference.WrittenScale))
				{
					val2 = reference.WrittenRotation * Quaternion.Inverse(reference.Delta.Rotation);
					val3 = reference.WrittenPosition - reference.Delta.Position;
					val4 = Divide(reference.WrittenScale, reference.Delta.Scale);
				}
				BonePose delta = totalPose[i];
				Quaternion writtenRotation = (val.localRotation = val2 * delta.Rotation);
				reference.WrittenRotation = writtenRotation;
				Vector3 writtenPosition = (val.localPosition = val3 + delta.Position);
				reference.WrittenPosition = writtenPosition;
				writtenPosition = (val.localScale = Vector3.Scale(val4, delta.Scale));
				reference.WrittenScale = writtenPosition;
				reference.Delta = delta;
				reference.Valid = true;
			}
			anyApplied = true;
		}

		private void Restore()
		{
			//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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0072: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < bones.Length; i++)
			{
				Transform val = bones[i];
				ref Applied reference = ref applied[i];
				if (reference.Valid && Object.op_Implicit((Object)(object)val))
				{
					Quaternion localRotation = val.localRotation;
					if (((Quaternion)(ref localRotation)).Equals(reference.WrittenRotation))
					{
						Vector3 localPosition = val.localPosition;
						if (((Vector3)(ref localPosition)).Equals(reference.WrittenPosition))
						{
							val.localRotation = reference.WrittenRotation * Quaternion.Inverse(reference.Delta.Rotation);
							val.localPosition = reference.WrittenPosition - reference.Delta.Position;
							val.localScale = Divide(reference.WrittenScale, reference.Delta.Scale);
						}
					}
				}
				reference.Valid = false;
			}
			anyApplied = false;
		}

		private static Vector3 Divide(Vector3 a, Vector3 b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0022: 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_003d: 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_0044: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3((b.x != 0f) ? (a.x / b.x) : a.x, (b.y != 0f) ? (a.y / b.y) : a.y, (b.z != 0f) ? (a.z / b.z) : a.z);
		}
	}
	internal struct BonePose
	{
		public Quaternion Rotation;

		public Vector3 Position;

		public Vector3 Scale;

		public float RotationWeight;

		public float ScaleWeight;

		internal static readonly BonePose Identity = new BonePose
		{
			Rotation = Quaternion.identity,
			Position = Vector3.zero,
			Scale = Vector3.one
		};

		internal static readonly BonePose Empty = new BonePose
		{
			Rotation = new Quaternion(0f, 0f, 0f, 0f),
			Position = Vector3.zero,
			Scale = Vector3.zero
		};

		internal BonePose Resolve()
		{
			//IL_0047: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0070: 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_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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_00c2: 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_00cf: 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_00f2: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp01(1f - RotationWeight);
			Quaternion val = default(Quaternion);
			((Quaternion)(ref val))..ctor(Rotation.x, Rotation.y, Rotation.z, Rotation.w + num);
			float num2 = Mathf.Sqrt(val.x * val.x + val.y * val.y + val.z * val.z + val.w * val.w);
			return new BonePose
			{
				Rotation = (Quaternion)((num2 > 1E-06f) ? new Quaternion(val.x / num2, val.y / num2, val.z / num2, val.w / num2) : Quaternion.identity),
				Position = Position,
				Scale = Scale + Vector3.one * Mathf.Clamp01(1f - ScaleWeight)
			};
		}
	}
	internal sealed class LayerState
	{
		private struct Slot
		{
			public Clip Clip;

			public float Time;

			public float Speed;

			public float ExitNormalized;

			public float ExitSeconds;
		}

		private Slot current;

		private Slot next;

		private bool transitioning;

		private float transitionElapsed;

		private float transitionSeconds;

		internal float Fade = 1f;

		internal bool Active
		{
			get
			{
				if (current.Clip == null)
				{
					if (transitioning)
					{
						return next.Clip != null;
					}
					return false;
				}
				return true;
			}
		}

		internal void Play(Clip clip, float speed, float exitNormalized = 0f, float exitSeconds = 0f)
		{
			current = new Slot
			{
				Clip = clip,
				Speed = speed,
				ExitNormalized = exitNormalized,
				ExitSeconds = exitSeconds
			};
			next = default(Slot);
			transitioning = false;
		}

		internal void CrossFade(Clip clip, float speed, float seconds)
		{
			if (transitioning && transitionElapsed >= transitionSeconds * 0.5f)
			{
				current = next;
			}
			next = new Slot
			{
				Clip = clip,
				Speed = speed
			};
			transitioning = true;
			transitionElapsed = 0f;
			transitionSeconds = Mathf.Max(seconds, 0.0001f);
		}

		internal void Stop()
		{
			current = default(Slot);
			next = default(Slot);
			transitioning = false;
		}

		internal void Advance(float dt)
		{
			current.Time += dt * current.Speed;
			if (transitioning)
			{
				next.Time += dt * next.Speed;
				transitionElapsed += dt;
				if (transitionElapsed >= transitionSeconds)
				{
					current = next;
					next = default(Slot);
					transitioning = false;
				}
			}
			if (!transitioning && current.Clip != null && current.ExitNormalized > 0f && current.Time >= current.ExitNormalized * current.Clip.Length)
			{
				CrossFade(null, 1f, current.ExitSeconds);
			}
			if (!transitioning && current.Clip == null)
			{
				current = default(Slot);
			}
		}

		internal void Accumulate(BonePose[] pose)
		{
			float num = (transitioning ? Mathf.Clamp01(transitionElapsed / transitionSeconds) : 0f);
			Add(pose, current, (1f - num) * Fade);
			if (transitioning)
			{
				Add(pose, next, num * Fade);
			}
		}

		private static void Add(BonePose[] pose, Slot slot, float weight)
		{
			//IL_0054: 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_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: 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_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00af: 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)
			if (slot.Clip == null || weight <= 0f)
			{
				return;
			}
			float t = Mathf.Clamp(slot.Time, 0f, slot.Clip.Length);
			Track[] tracks = slot.Clip.Tracks;
			foreach (Track track in tracks)
			{
				ref BonePose reference = ref pose[track.Bone];
				Vector3 val = track.Sample(t);
				switch (track.Kind)
				{
				case TrackKind.Euler:
				{
					Quaternion val2 = track.InverseReferenceRotation * Quaternion.Euler(val);
					if (val2.w < 0f)
					{
						((Quaternion)(ref val2))..ctor(0f - val2.x, 0f - val2.y, 0f - val2.z, 0f - val2.w);
					}
					reference.Rotation = new Quaternion(reference.Rotation.x + val2.x * weight, reference.Rotation.y + val2.y * weight, reference.Rotation.z + val2.z * weight, reference.Rotation.w + val2.w * weight);
					reference.RotationWeight += weight;
					break;
				}
				case TrackKind.Position:
				{
					ref Vector3 position = ref reference.Position;
					position += (val - track.Reference) * weight;
					break;
				}
				case TrackKind.Scale:
				{
					ref Vector3 scale = ref reference.Scale;
					scale += new Vector3(Ratio(val.x, track.Reference.x), Ratio(val.y, track.Reference.y), Ratio(val.z, track.Reference.z)) * weight;
					reference.ScaleWeight += weight;
					break;
				}
				}
			}
		}

		private static float Ratio(float value, float reference)
		{
			if (reference == 0f)
			{
				return 1f;
			}
			return value / reference;
		}
	}
	internal static class Patches
	{
		private static EffectIndex flashIndex = (EffectIndex)(-1);

		private static bool flashResolved;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Paint), "OnEnter")]
		private static void PaintEnter(Paint __instance)
		{
			Guard((EntityState)(object)__instance, delegate(HarpoonRig rig)
			{
				rig.PaintEntered();
			});
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Paint), "OnExit")]
		private static void PaintExit(Paint __instance)
		{
			Guard((EntityState)(object)__instance, delegate(HarpoonRig rig)
			{
				rig.PaintExited();
			});
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Fire), "OnEnter")]
		private static void FireEnter(Fire __instance)
		{
			Guard((EntityState)(object)__instance, delegate(HarpoonRig rig)
			{
				rig.FireEntered();
			});
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Fire), "OnExit")]
		private static void FireExit(Fire __instance)
		{
			Guard((EntityState)(object)__instance, delegate(HarpoonRig rig)
			{
				rig.FireExited();
			});
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(EffectManager), "SpawnEffect", new Type[]
		{
			typeof(EffectIndex),
			typeof(EffectData),
			typeof(bool)
		})]
		private static void SpawnEffectPrefix(EffectIndex effectIndex, EffectData effectData, bool transmit)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (effectIndex != flashIndex || (int)effectIndex == -1 || !NetworkClient.active || (transmit && NetworkServer.active))
			{
				return;
			}
			try
			{
				OnFlash(effectData);
			}
			catch (Exception ex)
			{
				HarpoonAnimFixPlugin.Log.LogError((object)ex);
			}
		}

		private static void Guard(EntityState state, Action<HarpoonRig> action)
		{
			try
			{
				ResolveFlash();
				HarpoonRig harpoonRig = HarpoonRig.For(GetAnimator(Object.op_Implicit((Object)(object)state.outer) ? state.outer.commonComponents.modelLocator : null));
				if (Object.op_Implicit((Object)(object)harpoonRig))
				{
					action(harpoonRig);
				}
			}
			catch (Exception ex)
			{
				HarpoonAnimFixPlugin.Log.LogError((object)ex);
			}
		}

		private static void OnFlash(EffectData data)
		{
			GameObject rootObject = data.rootObject;
			if (Object.op_Implicit((Object)(object)rootObject))
			{
				ModelLocator component = rootObject.GetComponent<ModelLocator>();
				HarpoonRig harpoonRig = HarpoonRig.For(GetAnimator(component));
				if (Object.op_Implicit((Object)(object)harpoonRig))
				{
					ChildLocator val = (Object.op_Implicit((Object)(object)component.modelTransform) ? ((Component)component.modelTransform).GetComponent<ChildLocator>() : null);
					string text = ((Object.op_Implicit((Object)(object)val) && data.modelChildIndex >= 0) ? val.FindChildName((int)data.modelChildIndex) : null);
					harpoonRig.Shot(text != null && text.IndexOf("Left", StringComparison.OrdinalIgnoreCase) >= 0);
				}
			}
		}

		private static Animator GetAnimator(ModelLocator locator)
		{
			if (!Object.op_Implicit((Object)(object)locator))
			{
				return null;
			}
			if (Object.op_Implicit((Object)(object)locator.modelAnimator))
			{
				return locator.modelAnimator;
			}
			if (!Object.op_Implicit((Object)(object)locator.modelTransform))
			{
				return null;
			}
			return ((Component)locator.modelTransform).GetComponent<Animator>();
		}

		private static void ResolveFlash()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			if (flashResolved)
			{
				return;
			}
			GameObject muzzleflashEffectPrefab = Fire.muzzleflashEffectPrefab;
			if (Object.op_Implicit((Object)(object)muzzleflashEffectPrefab))
			{
				flashResolved = true;
				flashIndex = EffectCatalog.FindEffectIndexFromPrefab(muzzleflashEffectPrefab);
				if ((int)flashIndex == -1)
				{
					HarpoonAnimFixPlugin.Log.LogWarning((object)("Harpoon muzzle flash '" + ((Object)muzzleflashEffectPrefab).name + "' is not in the effect catalog; cannon recoil will not play."));
				}
			}
		}
	}
}