Decompiled source of Iaido Katana v0.1.2

Iaido_Katana.dll

Decompiled 10 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.PostProcessing;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Iaido_Katana")]
[assembly: AssemblyDescription("A two-handed katana for Valheim that strikes back on a perfect parry")]
[assembly: AssemblyFileVersion("0.1.2.0")]
[assembly: InternalsVisibleTo("KatanaCheck")]
[assembly: InternalsVisibleTo("StancePreview")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.1.2.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 Iaido_Katana
{
	internal static class Counter
	{
		private const float CounterPush = 5f;

		private const float SwingTimeout = 0.6f;

		private const float SwingMaxTime = 1f;

		private static readonly FieldRef<Character, ZSyncAnimation> ZAnim = AccessTools.FieldRefAccess<Character, ZSyncAnimation>("m_zanim");

		private static readonly FieldRef<Character, CharacterAnimEvent> AnimEvent = AccessTools.FieldRefAccess<Character, CharacterAnimEvent>("m_animEvent");

		private static bool _swinging;

		private static bool _swingSeen;

		private static float _swingStart;

		private static Player _player;

		private static Character _attacker;

		private static bool _ranged;

		private static float _parryTime;

		private static int _id;

		internal static bool AnimationPlaying => _swinging;

		internal static void StepSwing(Player player, Animator animator, bool paused)
		{
			if (!_swinging)
			{
				return;
			}
			if (Time.time - _swingStart > 1f || (!((Character)player).InAttack() && (_swingSeen || Time.time - _swingStart > 0.3f)))
			{
				EndSwing();
				return;
			}
			if (((Character)player).InAttack())
			{
				_swingSeen = true;
			}
			if (!paused)
			{
				animator.speed = Plugin.CounterAnimationSpeed.Value;
			}
		}

		internal static void EndSwing()
		{
			_swinging = false;
		}

		internal static void Start(Player player, Character attacker, bool ranged)
		{
			if (Plugin.CounterEnabled.Value && Object.op_Implicit((Object)(object)attacker) && (!attacker.IsPlayer() || Plugin.CounterInPvP.Value))
			{
				_player = player;
				_attacker = attacker;
				_ranged = ranged;
				_parryTime = Time.time;
				_id++;
				if (IaiStance.SlashOn && IaiStance.HoldsKatana(player))
				{
					IaiStance.StartSlash(player);
					((MonoBehaviour)player).StartCoroutine(StrikeAfter(_id, Mathf.Max(Plugin.CounterDelay.Value, 0.11f)));
				}
				else
				{
					bool flag = Plugin.CounterAnimation.Value && PlaySwing(player);
					((MonoBehaviour)player).StartCoroutine(StrikeAfter(_id, flag ? 0.6f : Plugin.CounterDelay.Value));
				}
			}
		}

		internal static void OnSwingHit()
		{
			if (Object.op_Implicit((Object)(object)_player))
			{
				float num = Plugin.CounterDelay.Value - (Time.time - _parryTime);
				if (num > 0f)
				{
					((MonoBehaviour)_player).StartCoroutine(StrikeAfter(_id, num));
				}
				else
				{
					Strike(_id);
				}
			}
		}

		private static bool PlaySwing(Player player)
		{
			Attack val = ((Humanoid)player).GetCurrentWeapon()?.m_shared.m_attack;
			if (val == null || string.IsNullOrEmpty(val.m_attackAnimation))
			{
				return false;
			}
			ZAnim.Invoke((Character)(object)player).SetTrigger((val.m_attackChainLevels > 1) ? (val.m_attackAnimation + "0") : val.m_attackAnimation);
			_swinging = true;
			_swingSeen = false;
			_swingStart = Time.time;
			return true;
		}

		internal static void LocalFreeze(Character character, float seconds)
		{
			CharacterAnimEvent val = ((seconds > 0f && Object.op_Implicit((Object)(object)character)) ? AnimEvent.Invoke(character) : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				val.FreezeFrame(seconds);
			}
		}

		private static IEnumerator StrikeAfter(int id, float seconds)
		{
			yield return (object)new WaitForSeconds(seconds);
			Strike(id);
		}

		private static void Strike(int id)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_00b0: 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_00cb: 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_00d9: 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)
			//IL_00e9: 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_00fa: 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_0107: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: 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_01a5: Unknown result type (might be due to invalid IL or missing references)
			if (id != _id)
			{
				return;
			}
			Player player = _player;
			Character attacker = _attacker;
			bool ranged = _ranged;
			_player = null;
			_attacker = null;
			if (!Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead() || !Object.op_Implicit((Object)(object)attacker) || attacker.IsDead())
			{
				return;
			}
			ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon();
			if (Katana.IsKatana(currentWeapon))
			{
				float num = Katana.CounterFactor(((Character)player).GetRandomSkillFactor((SkillType)1), ((Character)player).GetSkillFactor((SkillType)6), ranged, Plugin.CounterMultiplier.Value, Plugin.BlockBonusMax.Value, Plugin.ReflectMultiplier.Value) * Katana.PreciseFactor(Plugin.ParryPrecise.Value, Plugin.ParryPreciseBonus.Value);
				HitData val = new HitData();
				val.m_damage = currentWeapon.GetDamage();
				((DamageTypes)(ref val.m_damage)).Modify(num);
				val.m_point = attacker.GetCenterPoint();
				Vector3 val2 = val.m_point - ((Character)player).GetCenterPoint();
				val.m_dir = ((Vector3)(ref val2)).normalized;
				val.m_attacker = ((Character)player).GetZDOID();
				val.m_skill = (SkillType)1;
				val.m_hitType = (HitType)2;
				val.m_toolTier = (short)currentWeapon.m_shared.m_toolTier;
				val.m_pushForce = 5f;
				val.m_blockable = false;
				val.m_dodgeable = false;
				attacker.Damage(val);
				KatanaFx.HitEffect(currentWeapon.m_shared.m_hitEffect, val.m_point, Quaternion.LookRotation(val.m_dir), ImpactFrame.InkHides);
				LocalFreeze((Character)(object)player, Plugin.ImpactFreeze.Value);
				LocalFreeze(attacker, Plugin.ImpactFreeze.Value);
				IaiStance.HoldSlash(player, Plugin.ImpactFreeze.Value);
				ImpactFrame.Play(val.m_point);
				((Character)player).RaiseSkill((SkillType)1, 1f);
				if (Plugin.LogCounters.Value)
				{
					Plugin.Log.LogInfo((object)string.Format("counter on {0}: {1:0} before resistances and stagger (x{2:0.00} of the katana{3}{4}, {5:0.00} s after the parry)", attacker.m_name, ((DamageTypes)(ref val.m_damage)).GetTotalDamage(), num, ranged ? ", reflected" : "", Plugin.ParryPrecise.Value ? ", precise" : "", Time.time - _parryTime));
				}
			}
		}
	}
	internal static class Diagnostics
	{
		private static bool _dumped;

		private static string _lastPlaying;

		internal static void Step(Player player, Animator animator)
		{
			if (!Plugin.DumpAnimationClips.Value || !Object.op_Implicit((Object)(object)animator) || !Object.op_Implicit((Object)(object)animator.runtimeAnimatorController))
			{
				return;
			}
			if (!_dumped)
			{
				_dumped = true;
				RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController;
				List<string> list = (from n in (from c in runtimeAnimatorController.animationClips
						where Object.op_Implicit((Object)(object)c)
						select ((Object)c).name).Distinct()
					orderby n
					select n).ToList();
				Plugin.Log.LogInfo((object)($"player animator '{((Object)runtimeAnimatorController).name}': {animator.layerCount} layers, {list.Count} clips, " + (animator.isHuman ? "humanoid rig (animations can be retargeted)" : "generic rig (animations must be made on this skeleton)") + ", avatar '" + (Object.op_Implicit((Object)(object)animator.avatar) ? ((Object)animator.avatar).name : "none") + "'"));
				for (int num = 0; num < animator.layerCount; num++)
				{
					Plugin.Log.LogInfo((object)$"  layer {num}: {animator.GetLayerName(num)}");
				}
				Plugin.Log.LogInfo((object)("  clips: " + string.Join(", ", list)));
				Plugin.Log.LogInfo((object)("  parameters: " + string.Join(", ", animator.parameters.Select((AnimatorControllerParameter p) => $"{p.name} ({p.type})"))));
			}
			if (!Katana.IsKatana(((Humanoid)player).GetCurrentWeapon()))
			{
				return;
			}
			List<string> list2 = new List<string>();
			for (int num2 = 0; num2 < animator.layerCount; num2++)
			{
				if (!(animator.GetLayerWeight(num2) <= 0.01f) || num2 <= 0)
				{
					IEnumerable<string> values = from c in animator.GetCurrentAnimatorClipInfo(num2)
						where Object.op_Implicit((Object)(object)((AnimatorClipInfo)(ref c)).clip)
						select ((Object)((AnimatorClipInfo)(ref c)).clip).name;
					list2.Add(string.Format("{0}:{1}", num2, string.Join("+", values)));
				}
			}
			string text = string.Join(" | ", list2) + (((Character)player).IsBlocking() ? " [blocking]" : "") + (((Character)player).InAttack() ? " [attack]" : "");
			if (!(text == _lastPlaying))
			{
				_lastPlaying = text;
				Plugin.Log.LogInfo((object)("playing: " + text));
			}
		}
	}
	internal static class IaiStance
	{
		private sealed class State
		{
			internal Transform[] Bones;

			internal Transform Hips;

			internal Transform Attach;

			internal readonly Quaternion[] Animated = (Quaternion[])(object)new Quaternion[BoneNames.Length];

			internal readonly Quaternion[] Written = (Quaternion[])(object)new Quaternion[BoneNames.Length];

			internal bool HasWritten;

			internal float Weight;

			internal bool Broken;

			internal float SlashStart = -1f;

			internal int SeenSlashes = -1;

			internal float HoldUntil = -1f;

			internal float HoldAt;

			internal float SettleStart = -1f;

			internal bool SayaFollows;

			internal float FollowStart = -1f;

			internal Vector3 FollowPos;

			internal Quaternion FollowRot;

			internal GameObject PutAwayLightning;

			internal Moves.Pose SettleFrom;

			internal int Move;

			internal int MoveStep;

			internal bool MoveFromScabbard;

			internal float MoveStart;

			internal float MoveClipStart;

			internal float MoveHold;

			internal bool MoveClicked;

			internal Moves.Pose MoveFrom;

			internal Moves.Pose LastPose;

			internal bool HasLast;

			internal bool LastSheathed;

			internal bool WasAttacking;

			internal bool HidePending;

			internal GameObject Saya;

			internal int SayaItem;

			internal Vector3 SayaMouth;

			internal GameObject Lightning;

			internal Vector3 SheathPos;

			internal Quaternion SheathRot;

			internal bool HasSheath;

			internal Transform Blade;

			internal Vector3 HipPos;

			internal Quaternion HipRot;

			internal bool HasHip;

			internal GameObject Sheathed;

			internal GameObject HiddenBack;

			internal ParticleSystem Sparks;

			internal bool InSlash;

			internal bool TrailOn;

			internal BladeTrail Trail;

			internal float Body;

			internal float ThunderStart = -1f;

			internal float ThunderPrep;

			internal int SeenThunder = -1;

			internal int ThunderStage;

			internal Vector3 AnimatedHips;

			internal Vector3 WrittenHips;

			internal readonly StanceSolver.ElbowMemory Elbows = new StanceSolver.ElbowMemory();

			internal bool RollSheathed;

			internal float HeavyAt = -9f;

			internal int SeenHeavy = -1;

			internal GameObject HiddenHand;

			internal float SpineLogAt;
		}

		private static readonly FieldRef<Character, Animator> AnimatorOf = AccessTools.FieldRefAccess<Character, Animator>("m_animator");

		private static readonly FieldRef<Humanoid, VisEquipment> VisOf = AccessTools.FieldRefAccess<Humanoid, VisEquipment>("m_visEquipment");

		private static readonly FieldRef<VisEquipment, int> RightItem = AccessTools.FieldRefAccess<VisEquipment, int>("m_currentRightItemHash");

		private static readonly FieldRef<Character, ZNetView> NViewOf = AccessTools.FieldRefAccess<Character, ZNetView>("m_nview");

		private static readonly FieldRef<VisEquipment, int> BackItem = AccessTools.FieldRefAccess<VisEquipment, int>("m_currentRightBackItemHash");

		private static readonly FieldRef<VisEquipment, GameObject> BackInstance = AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_rightBackItemInstance");

		private static readonly FieldRef<VisEquipment, GameObject> HandInstance = AccessTools.FieldRefAccess<VisEquipment, GameObject>("m_rightItemInstance");

		private const float TrailFrom = 0.04f;

		private const float TrailTo = 0.2f;

		private static readonly int SlashCount = StringExtensionMethods.GetStableHashCode("IaidoKatana_slash");

		private static readonly int ThunderCount = StringExtensionMethods.GetStableHashCode("IaidoKatana_thunder");

		private static readonly int ThunderStop = StringExtensionMethods.GetStableHashCode("IaidoKatana_thunder_stop");

		private static readonly int ThunderPrepKey = StringExtensionMethods.GetStableHashCode("IaidoKatana_thunder_prep");

		private static readonly int HeavyCount = StringExtensionMethods.GetStableHashCode("IaidoKatana_heavy");

		private static readonly CrouchSettings Crouch = new CrouchSettings();

		private static readonly int SteelHash = StringExtensionMethods.GetStableHashCode("IaidoKatanaSteel");

		private static readonly int FlametalHash = StringExtensionMethods.GetStableHashCode("IaidoKatanaFlametal");

		private static readonly string[] BoneNames = new string[17]
		{
			"Spine1", "Spine2", "Neck", "RightArm", "RightForeArm", "RightHand", "LeftArm", "LeftForeArm", "LeftHand", "Hips",
			"LeftUpLeg", "LeftLeg", "LeftFoot", "RightUpLeg", "RightLeg", "RightFoot", "Spine"
		};

		private const int Spine1 = 0;

		private const int Spine2 = 1;

		private const int Neck = 2;

		private const int RArm = 3;

		private const int RFore = 4;

		private const int RHand = 5;

		private const int LArm = 6;

		private const int LFore = 7;

		private const int LHand = 8;

		private const int HipsBone = 9;

		private const int LUp = 10;

		private const int LLow = 11;

		private const int LFoot = 12;

		private const int RUp = 13;

		private const int RLow = 14;

		private const int RFoot = 15;

		private const int SpineLow = 16;

		private static readonly Quaternion RestHipsRot = new Quaternion(0.7071068f, 0f, 0f, 0.7071068f);

		private static readonly Vector3 RestHipsLocal = new Vector3(0f, 7.026316E-05f, 0.009579787f);

		private static readonly Quaternion[] RestLegs = (Quaternion[])(object)new Quaternion[6]
		{
			new Quaternion(0.00026014916f, -0.03361914f, 0.9994042f, 0.0078065796f),
			new Quaternion(-0.0042211507f, -2.2611024E-05f, 0.003433189f, 0.9999852f),
			new Quaternion(0.48492208f, -0.03238013f, 0.017970623f, 0.873773f),
			new Quaternion(-0.00026014916f, -0.03361914f, 0.9994042f, -0.0078065796f),
			new Quaternion(-0.0038573912f, 2.066251E-05f, -0.0031373324f, 0.99998766f),
			new Quaternion(0.48492208f, 0.03238013f, -0.017970623f, 0.873773f)
		};

		private const float BodyIn = 0.12f;

		private const float BodyOut = 0.25f;

		private const float SettleSeconds = 0.2f;

		private const float FollowEase = 0.1f;

		private const float ElbowTurnSpeed = 900f;

		private static readonly CrouchSettings Footing = new CrouchSettings();

		private static readonly Quaternion[] KeptBody = (Quaternion[])(object)new Quaternion[7];

		private static readonly Quaternion RestSpine = new Quaternion(-0.03922647f, 0f, 0f, 0.9992304f);

		private static readonly Quaternion RestSpine1 = new Quaternion(-0.010170685f, 0f, 0f, 0.9999483f);

		private static readonly Quaternion RestSpine2 = new Quaternion(0f, 0f, 0f, 1f);

		private static readonly Quaternion RestNeck = new Quaternion(0.34641975f, -0.008183268f, 0.026077881f, 0.9376814f);

		private const float HeavyWindow = 0.6f;

		private static int _dodgeTag;

		private static readonly StanceSettings SayaSettings = new StanceSettings();

		private const string ComboClip = "Greatsword BaseAttack (";

		private const string HeavyClip = "Sledge-Attack1";

		private static readonly List<AnimatorClipInfo> ClipBuffer = new List<AnimatorClipInfo>();

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

		private static readonly StanceSettings Settings = new StanceSettings();

		private static readonly Quaternion[] Pose = (Quaternion[])(object)new Quaternion[BoneNames.Length];

		private static int _forwardSpeed;

		private static int _sidewaySpeed;

		private static readonly StanceSettings SlashSettings = new StanceSettings();

		private static readonly StanceSettings Defaults = new StanceSettings();

		private static readonly Vector3 DefaultLeftHand = Defaults.LeftHand;

		private static int DodgeTag
		{
			get
			{
				if (_dodgeTag == 0)
				{
					return _dodgeTag = Animator.StringToHash("dodge");
				}
				return _dodgeTag;
			}
		}

		internal static bool SlashOn
		{
			get
			{
				if (Plugin.StanceEnabled.Value)
				{
					return Plugin.StanceSlash.Value;
				}
				return false;
			}
		}

		internal static void StartHeavy(Player player)
		{
			State state = StateOf(player);
			state.HeavyAt = Time.time;
			ZNetView obj = NViewOf.Invoke((Character)(object)player);
			ZDO val = ((obj != null) ? obj.GetZDO() : null);
			if (val != null)
			{
				int num = val.GetInt(HeavyCount, 0) + 1;
				val.Set(HeavyCount, num, false);
				state.SeenHeavy = num;
			}
		}

		private static void WatchHeavy(Player player, State s)
		{
			ZNetView val = NViewOf.Invoke((Character)(object)player);
			if (Object.op_Implicit((Object)(object)val) && val.IsValid() && !val.IsOwner())
			{
				int num = val.GetZDO().GetInt(HeavyCount, 0);
				if (s.SeenHeavy >= 0 && num != s.SeenHeavy)
				{
					s.HeavyAt = Time.time;
				}
				s.SeenHeavy = num;
			}
		}

		internal static void StartThunder(Player player, float prep)
		{
			State state = StateOf(player);
			state.ThunderStart = Time.time;
			state.ThunderPrep = prep;
			state.ThunderStage = 0;
			ZNetView obj = NViewOf.Invoke((Character)(object)player);
			ZDO val = ((obj != null) ? obj.GetZDO() : null);
			if (val != null)
			{
				int num = val.GetInt(ThunderCount, 0) + 1;
				val.Set(ThunderPrepKey, prep);
				val.Set(ThunderCount, num, false);
				state.SeenThunder = num;
			}
		}

		internal static void StopThunder(Player player)
		{
			if (States.TryGetValue(player, out var value))
			{
				EndThunder(player, value);
			}
			ZNetView obj = NViewOf.Invoke((Character)(object)player);
			ZDO val = ((obj != null) ? obj.GetZDO() : null);
			if (val != null)
			{
				val.Set(ThunderStop, val.GetInt(ThunderCount, 0), false);
			}
		}

		private static void EndThunder(Player player, State s)
		{
			s.ThunderStart = -1f;
		}

		private static void WatchThunder(Player player, State s)
		{
			ZNetView val = NViewOf.Invoke((Character)(object)player);
			if (Object.op_Implicit((Object)(object)val) && val.IsValid() && !val.IsOwner())
			{
				ZDO zDO = val.GetZDO();
				int num = zDO.GetInt(ThunderCount, 0);
				if (s.SeenThunder >= 0 && num != s.SeenThunder)
				{
					s.ThunderStart = Time.time;
					s.ThunderPrep = zDO.GetFloat(ThunderPrepKey, Plugin.ThunderPrep.Value);
					s.ThunderStage = 0;
				}
				s.SeenThunder = num;
				if (s.ThunderStart >= 0f && zDO.GetInt(ThunderStop, 0) == num)
				{
					EndThunder(player, s);
				}
			}
		}

		private static void ThunderEvents(Player player, State s, float t)
		{
			//IL_001b: 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)
			float thunderPrep = s.ThunderPrep;
			if (s.ThunderStage == 0 && t >= thunderPrep)
			{
				s.ThunderStage = 1;
				KatanaFx.Glint(Mouth(s));
			}
			if (s.ThunderStage == 1 && t >= thunderPrep + 0.12f)
			{
				s.ThunderStage = 2;
			}
			if (s.ThunderStage == 2 && t >= Thunder.SheathedAt(thunderPrep))
			{
				s.ThunderStage = 3;
				ImpactFrame.Click(Mouth(s));
			}
		}

		private static int PutAway(Player player)
		{
			VisEquipment val = VisOf.Invoke((Humanoid)(object)player);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return 0;
			}
			int num = BackItem.Invoke(val);
			if (num != SteelHash && num != FlametalHash)
			{
				return 0;
			}
			return num;
		}

		private static void HideSaya(State s)
		{
			if (Object.op_Implicit((Object)(object)s.Saya))
			{
				s.Saya.SetActive(false);
			}
			RestoreBack(s);
			if (Object.op_Implicit((Object)(object)s.HiddenHand))
			{
				s.HiddenHand.SetActive(true);
			}
			s.HiddenHand = null;
			s.RollSheathed = false;
		}

		private static void HideHand(Player player, State s, bool hide)
		{
			GameObject val = (hide ? HandInstance.Invoke(VisOf.Invoke((Humanoid)(object)player)) : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				if (val.activeSelf)
				{
					val.SetActive(false);
				}
				s.HiddenHand = val;
			}
			else
			{
				if (Object.op_Implicit((Object)(object)s.HiddenHand))
				{
					s.HiddenHand.SetActive(true);
				}
				s.HiddenHand = null;
			}
		}

		private static bool Rolling(Player player)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			Animator val = AnimatorOf.Invoke((Character)(object)player);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			AnimatorStateInfo val2 = val.GetCurrentAnimatorStateInfo(0);
			if (((AnimatorStateInfo)(ref val2)).tagHash != DodgeTag)
			{
				if (val.IsInTransition(0))
				{
					val2 = val.GetNextAnimatorStateInfo(0);
					return ((AnimatorStateInfo)(ref val2)).tagHash == DodgeTag;
				}
				return false;
			}
			return true;
		}

		private static void LogSpine(Player player, State s)
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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)
			s.SpineLogAt = Time.time + 2f;
			AnimatorOf.Invoke((Character)(object)player).GetCurrentAnimatorClipInfo(0, ClipBuffer);
			string arg = string.Join("+", from c in ClipBuffer
				where Object.op_Implicit((Object)(object)((AnimatorClipInfo)(ref c)).clip)
				select ((Object)((AnimatorClipInfo)(ref c)).clip).name);
			Plugin.Log.LogInfo((object)("spine: Spine " + Turn(RestSpine, s.Animated[16]) + " Spine1 " + Turn(RestSpine1, s.Animated[0]) + " Spine2 " + Turn(RestSpine2, s.Animated[1]) + $" Neck {Turn(RestNeck, s.Animated[2])} hips {s.AnimatedHips.y * 100f:0.00} | {arg}"));
			static string Turn(Quaternion rest, Quaternion animated)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: 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_003a: Unknown result type (might be due to invalid IL or missing references)
				Quaternion val = Quaternion.Inverse(rest) * animated;
				Vector3 eulerAngles = ((Quaternion)(ref val)).eulerAngles;
				return $"({W(eulerAngles.x):0}, {W(eulerAngles.y):0}, {W(eulerAngles.z):0})";
			}
			static float W(float a)
			{
				if (!(a > 180f))
				{
					return a;
				}
				return a - 360f;
			}
		}

		private static void RestoreBack(State s)
		{
			if (Object.op_Implicit((Object)(object)s.HiddenBack))
			{
				s.HiddenBack.SetActive(true);
			}
			s.HiddenBack = null;
		}

		private static Transform BladeOf(State s)
		{
			if (Object.op_Implicit((Object)(object)s.Blade) && s.Blade.IsChildOf(s.Attach))
			{
				return s.Blade;
			}
			s.Blade = null;
			MeshFilter[] componentsInChildren = ((Component)s.Attach).GetComponentsInChildren<MeshFilter>();
			foreach (MeshFilter val in componentsInChildren)
			{
				if (((Object)val).name == "katana")
				{
					s.Blade = ((Component)val).transform;
				}
			}
			return s.Blade;
		}

		private static void UpdateSaya(Player player, State s, bool katana, int back)
		{
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_046f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_041e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0438: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0442: Unknown result type (might be due to invalid IL or missing references)
			//IL_0444: Unknown result type (might be due to invalid IL or missing references)
			//IL_051c: Unknown result type (might be due to invalid IL or missing references)
			//IL_051e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0520: Unknown result type (might be due to invalid IL or missing references)
			//IL_0522: Unknown result type (might be due to invalid IL or missing references)
			//IL_0527: Unknown result type (might be due to invalid IL or missing references)
			//IL_053c: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0540: Unknown result type (might be due to invalid IL or missing references)
			//IL_0555: Unknown result type (might be due to invalid IL or missing references)
			//IL_0562: Unknown result type (might be due to invalid IL or missing references)
			//IL_0572: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0501: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0497: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			bool flag = !katana && back != 0 && Plugin.HolsterOn.Value;
			bool flag2 = katana && s.RollSheathed && s.HasHip;
			if (!(katana || flag) || !Plugin.StanceEnabled.Value || !Plugin.ScabbardOn.Value || ((Character)player).IsDead())
			{
				HideSaya(s);
				return;
			}
			Transform transform = ((Component)AnimatorOf.Invoke((Character)(object)player)).transform;
			int num = (katana ? RightItem.Invoke(VisOf.Invoke((Humanoid)(object)player)) : back);
			if (!Object.op_Implicit((Object)(object)s.Saya) || s.SayaItem != num)
			{
				string text = ((num == FlametalHash) ? "flametal" : "steel");
				Mesh val = KatanaModel.SayaMeshFor(text);
				Material val2 = KatanaModel.MaterialFor(text);
				if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
				{
					return;
				}
				if (!Object.op_Implicit((Object)(object)s.Saya))
				{
					s.Saya = new GameObject("IaidoKatana_saya", new Type[2]
					{
						typeof(MeshFilter),
						typeof(MeshRenderer)
					});
					s.Saya.transform.SetParent(transform, false);
					s.Saya.layer = ((Component)transform).gameObject.layer;
					s.Sheathed = new GameObject("IaidoKatana_sheathed", new Type[2]
					{
						typeof(MeshFilter),
						typeof(MeshRenderer)
					});
					s.Sheathed.transform.SetParent(s.Saya.transform, false);
					s.Sheathed.layer = s.Saya.layer;
				}
				s.Sheathed.GetComponent<MeshFilter>().sharedMesh = KatanaModel.KatanaMeshFor(text);
				if (Object.op_Implicit((Object)(object)s.PutAwayLightning))
				{
					Object.Destroy((Object)(object)s.PutAwayLightning);
				}
				s.PutAwayLightning = ((text == "flametal") ? KatanaFx.CopyLightning("IaidoKatanaFlametal", s.Sheathed.transform) : null);
				s.SayaMouth = KatanaModel.SayaMouthFor(text);
				s.Saya.GetComponent<MeshFilter>().sharedMesh = val;
				((Renderer)s.Saya.GetComponent<MeshRenderer>()).sharedMaterial = val2;
				((Renderer)s.Sheathed.GetComponent<MeshRenderer>()).sharedMaterial = val2;
				if (num == FlametalHash && !Object.op_Implicit((Object)(object)s.Sparks) && Plugin.SparksOn.Value)
				{
					s.Sparks = KatanaFx.Sparks(s.Saya.transform, s.SayaMouth);
				}
				s.SayaItem = num;
			}
			s.Saya.SetActive(true);
			s.Sheathed.SetActive(flag || flag2);
			GameObject val3 = (flag ? BackInstance.Invoke(VisOf.Invoke((Humanoid)(object)player)) : null);
			if (Object.op_Implicit((Object)(object)val3))
			{
				if (val3.activeSelf)
				{
					val3.SetActive(false);
				}
				s.HiddenBack = val3;
			}
			else
			{
				RestoreBack(s);
			}
			float strength = 0f;
			if (Plugin.SparksOn.Value && num == FlametalHash && katana)
			{
				float num2 = ((s.ThunderStart >= 0f) ? ((Time.time - s.ThunderStart) / Mathf.Max(0.1f, s.ThunderPrep)) : (-1f));
				if (num2 >= 0f)
				{
					strength = ((num2 < 1f) ? (1f + 5f * num2) : 0f);
				}
				else if (s.Weight >= 0.9f && !s.InSlash && s.Move == 0)
				{
					strength = 1f;
				}
			}
			KatanaFx.SparkRate(s.Sparks, strength);
			Quaternion rotation = ((Component)player).transform.rotation;
			Vector3 val4 = s.Hips.position - QMath.Rotate(rotation, StanceSolver.RestHips);
			Vector3 grip;
			Quaternion attach;
			if ((flag || flag2) && s.HasHip)
			{
				grip = s.Hips.position + QMath.Rotate(s.Hips.rotation, s.HipPos);
				attach = QMath.Mul(s.Hips.rotation, s.HipRot);
			}
			else if (s.HasSheath)
			{
				grip = val4 + QMath.Rotate(rotation, s.SayaFollows ? s.FollowPos : s.SheathPos);
				attach = QMath.Mul(rotation, s.SayaFollows ? s.FollowRot : s.SheathRot);
			}
			else
			{
				ReadSettings(SayaSettings);
				StanceSolver.Sword(val4, rotation, SayaSettings, out grip, out attach, out var _);
			}
			if (flag && !s.HasHip && Upright(player))
			{
				LearnHip(s, grip, attach);
			}
			Vector3 v = KatanaModel.NodePosition;
			Quaternion b = KatanaModel.NodeRotation;
			float num3 = 1f;
			Transform val5 = BladeOf(s);
			if (Object.op_Implicit((Object)(object)val5))
			{
				Quaternion val6 = QMath.Conj(s.Attach.rotation);
				v = QMath.Rotate(val6, val5.position - s.Attach.position);
				b = QMath.Mul(val6, val5.rotation);
				num3 = val5.lossyScale.x;
			}
			s.Saya.transform.position = grip + QMath.Rotate(attach, v);
			s.Saya.transform.rotation = QMath.Mul(attach, b);
			s.Saya.transform.localScale = Vector3.one * (num3 / Mathf.Max(0.0001f, transform.lossyScale.x));
		}

		private static bool Upright(Player player)
		{
			if (((Character)player).IsOnGround() && !((Character)player).IsSwimming() && !((Character)player).IsAttached() && !((Character)player).InBed())
			{
				return !((Character)player).IsSitting();
			}
			return false;
		}

		private static void LearnHip(State s, Vector3 grip, Quaternion attach)
		{
			//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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = QMath.Conj(s.Hips.rotation);
			s.HipPos = QMath.Rotate(val, grip - s.Hips.position);
			s.HipRot = QMath.Mul(val, attach);
			s.HasHip = true;
		}

		private static Vector3 Mouth(State s)
		{
			//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)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)s.Saya) || !s.Saya.activeInHierarchy)
			{
				return s.Attach.position;
			}
			return s.Saya.transform.TransformPoint(s.SayaMouth);
		}

		private static void SlashBegins(State s)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			KatanaFx.Glint(Mouth(s));
		}

		private static bool AttackClip(Animator animator, State s, out int step, out float clipTime, out bool other)
		{
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: 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)
			step = -1;
			clipTime = 0f;
			other = false;
			if (!Object.op_Implicit((Object)(object)animator))
			{
				return false;
			}
			if (animator.layerCount > 1)
			{
				bool num = animator.IsInTransition(1);
				AnimatorStateInfo val = (num ? animator.GetNextAnimatorStateInfo(1) : animator.GetCurrentAnimatorStateInfo(1));
				if (num)
				{
					animator.GetNextAnimatorClipInfo(1, ClipBuffer);
				}
				else
				{
					animator.GetCurrentAnimatorClipInfo(1, ClipBuffer);
				}
				foreach (AnimatorClipInfo item in ClipBuffer)
				{
					AnimatorClipInfo current = item;
					if (Object.op_Implicit((Object)(object)((AnimatorClipInfo)(ref current)).clip))
					{
						int num2 = Array.IndexOf(Moves.UpperClips, ((Object)((AnimatorClipInfo)(ref current)).clip).name);
						if (num2 >= 0)
						{
							bool flag = num2 == 2 && ((s.Move == 1 && s.MoveStep == 3) || Time.time - s.HeavyAt < 0.6f);
							step = (flag ? 3 : num2);
							clipTime = Moves.KeyTime(step, ((AnimatorStateInfo)(ref val)).normalizedTime * ((AnimatorClipInfo)(ref current)).clip.length);
							return true;
						}
					}
				}
			}
			bool num3 = animator.IsInTransition(0);
			AnimatorStateInfo val2 = (num3 ? animator.GetNextAnimatorStateInfo(0) : animator.GetCurrentAnimatorStateInfo(0));
			if (num3)
			{
				animator.GetNextAnimatorClipInfo(0, ClipBuffer);
			}
			else
			{
				animator.GetCurrentAnimatorClipInfo(0, ClipBuffer);
			}
			foreach (AnimatorClipInfo item2 in ClipBuffer)
			{
				AnimatorClipInfo current2 = item2;
				if (Object.op_Implicit((Object)(object)((AnimatorClipInfo)(ref current2)).clip))
				{
					string name = ((Object)((AnimatorClipInfo)(ref current2)).clip).name;
					if (name.StartsWith("Greatsword BaseAttack (") && name.Length == "Greatsword BaseAttack (".Length + 2)
					{
						step = name["Greatsword BaseAttack (".Length] - 49;
						clipTime = ((AnimatorStateInfo)(ref val2)).normalizedTime * ((AnimatorClipInfo)(ref current2)).clip.length;
						return step >= 0 && step < Moves.Steps;
					}
					if (name == "Sledge-Attack1")
					{
						step = 3;
						clipTime = ((AnimatorStateInfo)(ref val2)).normalizedTime * ((AnimatorClipInfo)(ref current2)).clip.length;
						return true;
					}
					if (name.Contains("Attack"))
					{
						other = true;
					}
				}
			}
			return other;
		}

		private static void StartCombo(Player player, State s, int step, float clipTime)
		{
			s.MoveFrom = (s.HasLast ? s.LastPose : Shown(player, s));
			s.MoveFromScabbard = (step == 0 || step == 3) && s.HasLast && s.LastSheathed;
			s.Move = 1;
			s.MoveStep = step;
			s.MoveClipStart = clipTime;
			s.MoveStart = Time.time;
		}

		private static void StartSheathe(Player player, State s, float hold)
		{
			VisEquipment obj = VisOf.Invoke((Humanoid)(object)player);
			if (obj != null)
			{
				obj.SetWeaponTrails(false);
			}
			s.MoveFrom = (s.HasLast ? s.LastPose : Shown(player, s));
			s.Move = 2;
			s.MoveStart = Time.time;
			s.MoveHold = hold;
			s.MoveClicked = false;
		}

		private static void StepSheathe(Player player, State s, bool goOn)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (!goOn)
			{
				s.Move = 0;
				s.HidePending = false;
				return;
			}
			float num = Time.time - s.MoveStart;
			float value = Plugin.StanceNoto.Value;
			if (!s.MoveClicked && num >= Moves.SheathedAt(s.MoveHold, value))
			{
				s.MoveClicked = true;
				ImpactFrame.Click(Mouth(s));
			}
			if (!(num < Moves.SheatheLength(s.MoveHold, value)))
			{
				s.Move = 0;
				s.SettleStart = Time.time;
				s.SettleFrom = s.LastPose;
				if (s.HidePending && (Object)(object)player == (Object)(object)Player.m_localPlayer)
				{
					s.HidePending = false;
					((Humanoid)player).HideHandItems(false, true);
				}
			}
		}

		private static Moves.Pose Shown(Player player, State s)
		{
			//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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_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)
			//IL_0032: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0055: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			Quaternion rotation = ((Component)player).transform.rotation;
			Vector3 val = s.Hips.position - QMath.Rotate(rotation, StanceSolver.RestHips);
			return new Moves.Pose
			{
				Grip = QMath.Rotate(QMath.Conj(rotation), s.Attach.position - val),
				Rot = QMath.Mul(QMath.Conj(rotation), s.Attach.rotation),
				Along = Plugin.StanceLeftHand.Value
			};
		}

		internal static bool DelayHide(Player player)
		{
			if (!States.TryGetValue(player, out var value) || !HoldsKatana(player))
			{
				return false;
			}
			if (((Character)player).IsSwimming() || ((Character)player).InBed() || ((Character)player).IsAttached() || !((Character)player).IsOnGround())
			{
				return false;
			}
			if (value.Move == 0 && !value.InSlash && !value.WasAttacking)
			{
				return false;
			}
			value.HidePending = true;
			return true;
		}

		private static void Trail(Player player, State s, bool on)
		{
			s.TrailOn = on && Plugin.SlashTrailOn.Value;
		}

		private static void DrawTrail(Player player, State s, bool katana)
		{
			Transform val = (katana ? BladeOf(s) : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				s.Trail?.Clear();
				return;
			}
			if (s.Trail == null)
			{
				if (!s.TrailOn)
				{
					return;
				}
				s.Trail = BladeTrail.Make(((Component)player).transform, ((Component)val).gameObject.layer);
				if (s.Trail == null)
				{
					return;
				}
			}
			s.Trail.Sample(val, s.TrailOn, RightItem.Invoke(VisOf.Invoke((Humanoid)(object)player)) == FlametalHash);
		}

		internal static bool IsReadyClip(string name, bool running)
		{
			switch (name)
			{
			default:
				if ((running && (name.StartsWith("Jog New Sword Right") || name == "Run New Sword Right" || name.StartsWith("Jog Strafe Left") || name == "Jog backward")) || name.StartsWith("Greatsword Strafe") || name.StartsWith("Great sword walk") || name.StartsWith("Block"))
				{
					break;
				}
				if (running)
				{
					if (!name.StartsWith("Jog New Greatsword") && !(name == "Greatsword Jog") && !(name == "Run New Greatsword"))
					{
						return name.StartsWith("Greatsword Jump");
					}
					return true;
				}
				return false;
			case "Greatsword Idle":
			case "Walk New Greatsword":
			case "Greatsword Crouch Idle":
			case "Greatsword Sneak Walk":
			case "IdleTweaked":
			case "Walk New Sword Right":
			case "Crouch Idle":
			case "Sneak walk":
				break;
			}
			return true;
		}

		private static bool ReadyPose(Animator animator)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			animator.GetCurrentAnimatorClipInfo(0, ClipBuffer);
			float num = 0f;
			float num2 = 0f;
			foreach (AnimatorClipInfo item in ClipBuffer)
			{
				AnimatorClipInfo current = item;
				num2 += ((AnimatorClipInfo)(ref current)).weight;
				if (Object.op_Implicit((Object)(object)((AnimatorClipInfo)(ref current)).clip) && IsReadyClip(((Object)((AnimatorClipInfo)(ref current)).clip).name, Plugin.StanceReadyRunning.Value))
				{
					num += ((AnimatorClipInfo)(ref current)).weight;
				}
			}
			if (num2 > 0f)
			{
				return num >= num2 * 0.6f;
			}
			return false;
		}

		internal static void HoldSlash(Player player, float seconds)
		{
			if (!(seconds <= 0f) && States.TryGetValue(player, out var value) && !(value.SlashStart < 0f))
			{
				value.HoldAt = Time.time - value.SlashStart;
				value.HoldUntil = Time.time + seconds;
				value.SlashStart += seconds;
			}
		}

		internal static bool HoldsKatana(Player player)
		{
			VisEquipment val = VisOf.Invoke((Humanoid)(object)player);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			int num = RightItem.Invoke(val);
			if (num != SteelHash)
			{
				return num == FlametalHash;
			}
			return true;
		}

		internal static void StartSlash(Player player)
		{
			State state = StateOf(player);
			state.SlashStart = Time.time;
			state.HoldUntil = -1f;
			ZNetView obj = NViewOf.Invoke((Character)(object)player);
			ZDO val = ((obj != null) ? obj.GetZDO() : null);
			if (val != null)
			{
				int num = val.GetInt(SlashCount, 0) + 1;
				val.Set(SlashCount, num, false);
				state.SeenSlashes = num;
			}
		}

		private static State StateOf(Player player)
		{
			if (!States.TryGetValue(player, out var value))
			{
				value = new State();
				States.Add(player, value);
			}
			return value;
		}

		private static void WatchSlashes(Player player, State s)
		{
			ZNetView val = NViewOf.Invoke((Character)(object)player);
			if (Object.op_Implicit((Object)(object)val) && val.IsValid() && !val.IsOwner())
			{
				int num = val.GetZDO().GetInt(SlashCount, 0);
				if (s.SeenSlashes >= 0 && num != s.SeenSlashes)
				{
					s.SlashStart = Time.time;
					s.HoldUntil = -1f;
				}
				s.SeenSlashes = num;
			}
		}

		internal static void Step(Player player)
		{
			if (!Object.op_Implicit((Object)(object)player))
			{
				return;
			}
			if (!Plugin.StanceEnabled.Value)
			{
				if (States.TryGetValue(player, out var value))
				{
					HideSaya(value);
				}
				return;
			}
			bool flag = HoldsKatana(player);
			int num = ((!flag) ? PutAway(player) : 0);
			if (!States.TryGetValue(player, out var value2))
			{
				if (!flag && num == 0)
				{
					return;
				}
				value2 = StateOf(player);
			}
			if (!value2.Broken && Bind(player, value2))
			{
				StepPose(player, value2, flag);
				HideHand(player, value2, flag && value2.RollSheathed);
				UpdateSaya(player, value2, flag, num);
				UpdateCrackle(value2, flag);
				DrawTrail(player, value2, flag);
			}
		}

		private static void UpdateCrackle(State s, bool katana)
		{
			Transform val = (katana ? BladeOf(s) : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				if (!Object.op_Implicit((Object)(object)s.Lightning) || !s.Lightning.transform.IsChildOf(val))
				{
					Transform obj = val.Find("IaidoKatana_lightning");
					s.Lightning = ((obj != null) ? ((Component)obj).gameObject : null);
				}
				if (Object.op_Implicit((Object)(object)s.Lightning))
				{
					KatanaFx.Lightning(s.Lightning, on: true);
				}
			}
		}

		private static void StepPose(Player player, State s, bool katana)
		{
			//IL_0458: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Unknown result type (might be due to invalid IL or missing references)
			//IL_0467: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_058b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0522: Unknown result type (might be due to invalid IL or missing references)
			//IL_0545: Unknown result type (might be due to invalid IL or missing references)
			//IL_0816: Unknown result type (might be due to invalid IL or missing references)
			//IL_081b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0853: Unknown result type (might be due to invalid IL or missing references)
			//IL_0858: Unknown result type (might be due to invalid IL or missing references)
			//IL_0860: Unknown result type (might be due to invalid IL or missing references)
			//IL_0865: Unknown result type (might be due to invalid IL or missing references)
			//IL_0867: Unknown result type (might be due to invalid IL or missing references)
			//IL_086c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0871: Unknown result type (might be due to invalid IL or missing references)
			//IL_0876: Unknown result type (might be due to invalid IL or missing references)
			//IL_0879: Unknown result type (might be due to invalid IL or missing references)
			//IL_087b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0886: Unknown result type (might be due to invalid IL or missing references)
			//IL_088b: Unknown result type (might be due to invalid IL or missing references)
			//IL_088d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0892: Unknown result type (might be due to invalid IL or missing references)
			//IL_0897: Unknown result type (might be due to invalid IL or missing references)
			//IL_089d: Unknown result type (might be due to invalid IL or missing references)
			//IL_089f: Unknown result type (might be due to invalid IL or missing references)
			//IL_08aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_08af: Unknown result type (might be due to invalid IL or missing references)
			//IL_08b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0933: Unknown result type (might be due to invalid IL or missing references)
			//IL_0918: Unknown result type (might be due to invalid IL or missing references)
			//IL_0921: Unknown result type (might be due to invalid IL or missing references)
			//IL_0928: Unknown result type (might be due to invalid IL or missing references)
			//IL_098e: Unknown result type (might be due to invalid IL or missing references)
			//IL_097e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0983: Unknown result type (might be due to invalid IL or missing references)
			//IL_0987: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_08eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_094e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0953: Unknown result type (might be due to invalid IL or missing references)
			//IL_099c: Unknown result type (might be due to invalid IL or missing references)
			//IL_09a1: Unknown result type (might be due to invalid IL or missing references)
			if (SlashOn)
			{
				WatchSlashes(player, s);
			}
			bool flag = katana && !((Character)player).IsDead();
			float num = ((s.SlashStart < 0f) ? (-1f) : ((Time.time < s.HoldUntil) ? s.HoldAt : (Time.time - s.SlashStart)));
			bool flag2 = SlashOn && num >= 0f && num < 0.3f && flag;
			if (!flag2)
			{
				if (s.SlashStart >= 0f && num >= 0.3f && flag)
				{
					StartSheathe(player, s, Plugin.StanceZanshin.Value);
				}
				s.SlashStart = -1f;
			}
			else if (!s.InSlash)
			{
				SlashBegins(s);
			}
			s.InSlash = flag2;
			WatchThunder(player, s);
			WatchHeavy(player, s);
			float num2 = ((s.ThunderStart < 0f) ? (-1f) : (Time.time - s.ThunderStart));
			bool flag3 = num2 >= 0f && num2 < Thunder.Length(s.ThunderPrep) && katana && !((Character)player).IsDead();
			if (s.ThunderStart >= 0f && !flag3)
			{
				EndThunder(player, s);
			}
			if (flag3)
			{
				ThunderEvents(player, s, num2);
			}
			float clipTime = 0f;
			int step = -1;
			bool other = false;
			bool flag4 = flag && AttackClip(AnimatorOf.Invoke((Character)(object)player), s, out step, out clipTime, out other);
			if (flag4 && !other && Moves.OwnCuts && !flag3 && !flag2)
			{
				if (s.Move != 1 || s.MoveStep != step)
				{
					StartCombo(player, s, step, clipTime);
				}
			}
			else if (s.Move == 1)
			{
				s.Move = 0;
			}
			if (flag4)
			{
				s.WasAttacking = true;
			}
			else if (s.WasAttacking)
			{
				s.WasAttacking = false;
				if (flag && !Rolling(player) && !flag3 && !flag2 && s.Move == 0)
				{
					StartSheathe(player, s, 0f);
				}
			}
			bool flag5 = flag && Rolling(player);
			if (s.Move == 2)
			{
				StepSheathe(player, s, flag && !((Character)player).IsBlocking() && !flag5 && !flag3 && !flag2 && !flag4);
			}
			bool flag6 = s.Move != 0;
			bool flag7 = flag2 || flag6 || (flag3 && num2 >= s.ThunderPrep && num2 < Thunder.SheathedAt(s.ThunderPrep));
			Trail(player, s, (flag2 && num >= 0.04f && num < 0.2f) || (flag3 && num2 >= s.ThunderPrep && num2 < s.ThunderPrep + 0.12f) || (s.Move == 1 && Moves.InCut(s.MoveStep, clipTime)));
			float num3 = ((s.Move != 1) ? 0f : (Plugin.UpperBodySwings.Value ? Standing(player) : 1f));
			s.Body = (flag3 ? 0f : Mathf.MoveTowards(s.Body, num3, Time.deltaTime / ((num3 > s.Body) ? 0.12f : 0.25f)));
			bool flag8 = flag && !((Character)player).InAttack() && !flag5;
			bool flag9 = flag6 || (flag8 && (flag3 || ((Character)player).IsBlocking() || (Plugin.StanceReady.Value && ReadyPose(AnimatorOf.Invoke((Character)(object)player)))));
			float num4 = ((flag6 || (flag8 && (((Character)player).IsBlocking() || flag3))) ? Plugin.StanceBlendIn.Value : Plugin.StanceSheathe.Value);
			float num5 = (flag9 ? num4 : Plugin.StanceBlendOut.Value);
			s.Weight = (flag7 ? 1f : Mathf.MoveTowards(s.Weight, flag9 ? 1f : 0f, (num5 > 0f) ? (Time.deltaTime / num5) : 1f));
			if (flag5 && s.HasHip && Plugin.ScabbardOn.Value)
			{
				s.RollSheathed = true;
			}
			else if (s.RollSheathed && (!flag || flag7 || flag4 || !flag9 || s.Weight >= 0.99f))
			{
				s.RollSheathed = false;
			}
			for (int i = 0; i < s.Bones.Length; i++)
			{
				Quaternion localRotation = s.Bones[i].localRotation;
				if (!s.HasWritten || !Same(localRotation, s.Written[i]))
				{
					s.Animated[i] = localRotation;
				}
			}
			Vector3 localPosition = s.Hips.localPosition;
			if (!s.HasWritten || localPosition != s.WrittenHips)
			{
				s.AnimatedHips = localPosition;
			}
			if (Plugin.DumpAnimationClips.Value && (Object)(object)player == (Object)(object)Player.m_localPlayer && Time.time >= s.SpineLogAt)
			{
				LogSpine(player, s);
			}
			if (s.Weight <= 0f)
			{
				if (s.HasWritten)
				{
					for (int j = 0; j < s.Bones.Length; j++)
					{
						s.Bones[j].localRotation = s.Animated[j];
					}
					s.Hips.localPosition = s.AnimatedHips;
				}
				s.HasWritten = false;
				s.HasLast = false;
				s.Body = 0f;
				s.Elbows.Has = false;
				return;
			}
			for (int k = 0; k < s.Bones.Length; k++)
			{
				s.Bones[k].localRotation = s.Animated[k];
			}
			s.Hips.localPosition = s.AnimatedHips;
			ReadSettings(Settings);
			if (s.HasSheath)
			{
				Settings.SheathAt = s.SheathRot;
				Settings.SheathGrip = s.SheathPos;
			}
			float crouch = 0f;
			if (flag3)
			{
				Thunder.Sample(num2, s.ThunderPrep, Settings, SlashSettings, out crouch);
				CopyPose(SlashSettings, Settings);
				Crouch.HipTurn = Settings.HipTurn;
			}
			else if (flag2)
			{
				IaiSlash.Sample(num, Settings, SlashSettings);
				CopyPose(SlashSettings, Settings);
			}
			else if (s.Move == 1)
			{
				Moves.Combo(s.MoveStep, s.MoveFromScabbard, clipTime, s.MoveClipStart, s.MoveFrom, Settings, SlashSettings);
				CopyPose(SlashSettings, Settings);
			}
			else if (s.Move == 2)
			{
				Moves.Sheathe(Time.time - s.MoveStart, s.MoveHold, Plugin.StanceNoto.Value, s.MoveFrom, Settings, SlashSettings);
				CopyPose(SlashSettings, Settings);
			}
			else if (s.SettleStart >= 0f && Time.time - s.SettleStart < 0.2f && s.Weight >= 1f)
			{
				Moves.Settle(s.SettleFrom, (Time.time - s.SettleStart) / 0.2f, Settings, SlashSettings);
				CopyPose(SlashSettings, Settings);
			}
			else
			{
				s.SettleStart = -1f;
			}
			s.HasLast = s.Weight >= 0.999f;
			s.LastPose = Moves.FromSettings(Settings);
			s.LastSheathed = !flag7 && !flag3;
			if (s.Body > 0f)
			{
				Moves.Footing(s.MoveStep, (s.Move == 1) ? clipTime : 0f, Footing);
			}
			Footing.HipTurn = Settings.HipTurn;
			Quaternion[] array = FullPose(player, s, crouch, s.Move == 1, (s.Body > 0f) ? Footing : Crouch, s.Body);
			Vector3 localPosition2 = s.Hips.localPosition;
			FollowBlade(player, s);
			float num6 = s.Weight * s.Weight * (3f - 2f * s.Weight);
			if (!flag7)
			{
				Quaternion rotation = ((Component)player).transform.rotation;
				Vector3 val = s.Hips.position - QMath.Rotate(rotation, StanceSolver.RestHips);
				s.SheathPos = QMath.Rotate(QMath.Conj(rotation), s.Attach.position - val);
				s.SheathRot = QMath.Mul(QMath.Conj(rotation), s.Attach.rotation);
				s.HasSheath = true;
				if (s.Weight >= 1f && !flag3 && Upright(player))
				{
					LearnHip(s, s.Attach.position, s.Attach.rotation);
				}
			}
			for (int l = 0; l < s.Bones.Length; l++)
			{
				s.Bones[l].localRotation = ((s.Weight >= 1f) ? array[l] : QMath.Nlerp(s.Animated[l], array[l], num6));
				s.Written[l] = s.Bones[l].localRotation;
			}
			s.Hips.localPosition = ((s.Weight >= 1f) ? localPosition2 : Vector3.Lerp(s.AnimatedHips, localPosition2, num6));
			s.WrittenHips = s.Hips.localPosition;
			s.HasWritten = true;
		}

		private static void FollowBlade(Player player, State s)
		{
			//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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//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_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_0089: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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_010e: 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_011a: 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_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			float num = ((s.Move == 2) ? Moves.SlideOut(Time.time - s.MoveStart, s.MoveHold, Plugin.StanceNoto.Value) : (-1f));
			if (num < 0f || !s.HasSheath)
			{
				s.SayaFollows = false;
				s.FollowStart = -1f;
				return;
			}
			Quaternion rotation = ((Component)player).transform.rotation;
			Vector3 val = s.Hips.position - QMath.Rotate(rotation, StanceSolver.RestHips);
			Vector3 grip = QMath.Rotate(QMath.Conj(rotation), s.Attach.position - val);
			Quaternion rot = QMath.Mul(QMath.Conj(rotation), s.Attach.rotation);
			Moves.Slide(ref grip, ref rot, 0f - num);
			if (s.FollowStart < 0f)
			{
				s.FollowStart = Time.time;
			}
			float num2 = Mathf.Clamp01((Time.time - s.FollowStart) / 0.1f);
			num2 = num2 * num2 * (3f - 2f * num2);
			s.FollowPos = Vector3.Lerp(s.SheathPos, grip, num2);
			s.FollowRot = QMath.Nlerp(s.SheathRot, rot, num2);
			s.SayaFollows = true;
		}

		private static Quaternion[] FullPose(Player player, State s, float crouch, bool restSpine, CrouchSettings legs, float body)
		{
			//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_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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_005c: 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_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: 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_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: 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_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: 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_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: 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)
			Quaternion rotation = ((Component)player).transform.rotation;
			Transform[] bones = s.Bones;
			Quaternion b = default(Quaternion);
			((Quaternion)(ref b))..ctor(0f, 0f, 0f, 1f);
			if (restSpine)
			{
				bones[16].localRotation = RestSpine;
				bones[0].localRotation = RestSpine1;
				bones[1].localRotation = RestSpine2;
				bones[2].localRotation = RestNeck;
			}
			else
			{
				float t = Mathf.Clamp01(Plugin.StanceSpineHold.Value);
				bones[16].localRotation = QMath.Nlerp(bones[16].localRotation, RestSpine, t);
				bones[0].localRotation = QMath.Nlerp(bones[0].localRotation, RestSpine1, t);
				bones[1].localRotation = QMath.Nlerp(bones[1].localRotation, RestSpine2, t);
			}
			if (body > 0f)
			{
				for (int i = 9; i <= 15; i++)
				{
					KeptBody[i - 9] = bones[i].localRotation;
				}
				Vector3 localPosition = s.Hips.localPosition;
				bones[9].localRotation = RestHipsRot;
				s.Hips.localPosition = RestHipsLocal;
				for (int j = 10; j <= 15; j++)
				{
					bones[j].localRotation = RestLegs[j - 10];
				}
				Sink(player, s, 1f, legs);
				if (body < 1f)
				{
					for (int k = 9; k <= 15; k++)
					{
						bones[k].localRotation = QMath.Nlerp(KeptBody[k - 9], bones[k].localRotation, body);
					}
					s.Hips.localPosition = Vector3.Lerp(localPosition, s.Hips.localPosition, body);
				}
				b = StanceSolver.Turn(rotation, QMath.Euler(legs.HipPitch * body, legs.HipTurn * body, 0f));
			}
			else if (crouch > 0f)
			{
				Sink(player, s, crouch, legs);
				b = StanceSolver.Turn(rotation, QMath.Euler(legs.HipPitch * crouch, legs.HipTurn * crouch, 0f));
			}
			float num = (restSpine ? (Settings.HipTurn * (1f - body)) : 0f);
			if (num != 0f)
			{
				Drive(player, s, num);
				b = QMath.Mul(StanceSolver.Turn(rotation, QMath.Euler(0f, num, 0f)), b);
			}
			Quaternion a = StanceSolver.Half(StanceSolver.Spine(rotation, Settings));
			bones[0].rotation = QMath.Mul(a, bones[0].rotation);
			bones[1].rotation = QMath.Mul(a, bones[1].rotation);
			if (Settings.HeadForward)
			{
				bones[2].rotation = QMath.Mul(QMath.Conj(QMath.Mul(StanceSolver.Head(rotation, Settings), b)), bones[2].rotation);
			}
			Arm right = ArmOf(bones[3], bones[4], bones[5]);
			Arm left = ArmOf(bones[6], bones[7], bones[8]);
			Vector3 rootPos = s.Hips.position - QMath.Rotate(rotation, StanceSolver.RestHips);
			s.Elbows.MaxTurn = 900f * Time.deltaTime;
			StanceSolver.Solve(rootPos, rotation, Settings, ref right, ref left, s.Attach.localPosition, s.Attach.localRotation, bones[5].lossyScale.x, s.Elbows);
			bones[3].rotation = right.Upper;
			bones[4].rotation = right.Lower;
			bones[5].rotation = right.Hand;
			bones[6].rotation = left.Upper;
			bones[7].rotation = left.Lower;
			bones[8].rotation = left.Hand;
			for (int l = 0; l < bones.Length; l++)
			{
				Pose[l] = bones[l].localRotation;
			}
			return Pose;
		}

		private static void Drive(Player player, State s, float degrees)
		{
			//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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0059: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_0089: 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_00a8: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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)
			//IL_00f5: 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_011a: 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)
			Quaternion rotation = ((Component)player).transform.rotation;
			Vector3 position = ((Component)player).transform.position;
			Transform[] bones = s.Bones;
			Arm animated = ArmOf(bones[10], bones[11], bones[12]);
			Arm animated2 = ArmOf(bones[13], bones[14], bones[15]);
			bones[9].rotation = QMath.Mul(StanceSolver.Turn(rotation, QMath.Euler(0f, degrees, 0f)), bones[9].rotation);
			Arm leg = ArmOf(bones[10], bones[11], bones[12]);
			StanceSolver.Leg(ref leg, animated, position, rotation, Vector3.zero, 0f, Vector3.zero, 0f);
			bones[10].rotation = leg.Upper;
			bones[11].rotation = leg.Lower;
			bones[12].rotation = leg.Hand;
			Arm leg2 = ArmOf(bones[13], bones[14], bones[15]);
			StanceSolver.Leg(ref leg2, animated2, position, rotation, Vector3.zero, 0f, Vector3.zero, 0f);
			bones[13].rotation = leg2.Upper;
			bones[14].rotation = leg2.Lower;
			bones[15].rotation = leg2.Hand;
		}

		private static float Standing(Player player)
		{
			Animator val = AnimatorOf.Invoke((Character)(object)player);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return 1f;
			}
			if (_forwardSpeed == 0)
			{
				_forwardSpeed = Animator.StringToHash("forward_speed");
				_sidewaySpeed = Animator.StringToHash("sideway_speed");
			}
			float num = val.GetFloat(_forwardSpeed);
			float num2 = val.GetFloat(_sidewaySpeed);
			return 1f - Mathf.Clamp01((Mathf.Sqrt(num * num + num2 * num2) - 0.2f) / 0.6f);
		}

		private static void Sink(Player player, State s, float weight, CrouchSettings legs)
		{
			//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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0072: 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_0090: 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_009e: 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_00bf: 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_00f0: 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_00f3: 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_0110: 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_0130: Unknown result type (might be due to invalid IL or missing references)
			Quaternion rotation = ((Component)player).transform.rotation;
			Vector3 position = ((Component)player).transform.position;
			Transform[] bones = s.Bones;
			Arm animated = ArmOf(bones[10], bones[11], bones[12]);
			Arm animated2 = ArmOf(bones[13], bones[14], bones[15]);
			Vector3 pos = s.Hips.position;
			Quaternion rot = s.Hips.rotation;
			StanceSolver.Hips(rotation, legs, weight, ref pos, ref rot);
			s.Hips.SetPositionAndRotation(pos, rot);
			Arm leg = ArmOf(bones[10], bones[11], bones[12]);
			StanceSolver.Leg(ref leg, animated, position, rotation, legs.LeftFoot, legs.LeftFootTurn, legs.LeftKnee, weight);
			bones[10].rotation = leg.Upper;
			bones[11].rotation = leg.Lower;
			bones[12].rotation = leg.Hand;
			Arm leg2 = ArmOf(bones[13], bones[14], bones[15]);
			StanceSolver.Leg(ref leg2, animated2, position, rotation, legs.RightFoot, legs.RightFootTurn, legs.RightKnee, weight);
			bones[13].rotation = leg2.Upper;
			bones[14].rotation = leg2.Lower;
			bones[15].rotation = leg2.Hand;
		}

		private static Arm ArmOf(Transform upper, Transform lower, Transform hand)
		{
			//IL_000b: 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)
			//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_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_0032: 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_003f: 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_004c: 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)
			return new Arm
			{
				Shoulder = upper.position,
				Elbow = lower.position,
				Wrist = hand.position,
				Upper = upper.rotation,
				Lower = lower.rotation,
				Hand = hand.rotation
			};
		}

		private static void CopyPose(StanceSettings from, StanceSettings to)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_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)
			to.Grip = from.Grip;
			to.BladeYaw = from.BladeYaw;
			to.BladePitch = from.BladePitch;
			to.EdgeRoll = from.EdgeRoll;
			to.SpineTwist = from.SpineTwist;
			to.SpineLean = from.SpineLean;
			to.LeftOnBlade = from.LeftOnBlade;
			to.LeftAlongBlade = from.LeftAlongBlade;
			to.LeftHand = from.LeftHand;
			to.MouthAxis = from.MouthAxis;
			to.RightElbow = from.RightElbow;
			to.LeftElbow = from.LeftElbow;
			to.HipTurn = from.HipTurn;
			to.HeadDown = from.HeadDown;
			to.Attach = from.Attach;
		}

		private static void ReadSettings(StanceSettings into)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_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_005a: 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_009e: 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)
			into.Attach = null;
			into.SheathAt = null;
			into.LeftHand = DefaultLeftHand;
			into.MouthAxis = Vector3.zero;
			into.HipTurn = 0f;
			into.HeadDown = 0f;
			into.RightElbow = Defaults.RightElbow;
			into.LeftElbow = Defaults.LeftElbow;
			into.EdgeRoll = Defaults.EdgeRoll;
			into.LeftOnBlade = 1f;
			into.Grip = new Vector3(Plugin.StanceGripSide.Value, Plugin.StanceGripHeight.Value, Plugin.StanceGripForward.Value);
			into.BladeYaw = Plugin.StanceBladeYaw.Value;
			into.BladePitch = Plugin.StanceBladePitch.Value;
			into.SpineTwist = Plugin.StanceTwist.Value;
			into.SpineLean = Plugin.StanceLean.Value;
			into.LeftAlongBlade = Plugin.StanceLeftHand.Value;
		}

		private static bool Bind(Player player, State s)
		{
			if (s.Bones != null && Object.op_Implicit((Object)(object)s.Bones[0]))
			{
				return true;
			}
			Animator val = AnimatorOf.Invoke((Character)(object)player);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			Transform transform = ((Component)val).transform;
			s.Bones = (Transform[])(object)new Transform[BoneNames.Length];
			for (int i = 0; i < BoneNames.Length; i++)
			{
				if (!Object.op_Implicit((Object)(object)(s.Bones[i] = Find(transform, BoneNames[i]))))
				{
					return Fail(s, BoneNames[i]);
				}
			}
			s.Hips = Find(transform, "Hips");
			s.Attach = Find(transform, "RightHand_Attach");
			if (!Object.op_Implicit((Object)(object)s.Hips))
			{
				return Fail(s, "Hips");
			}
			if (!Object.op_Implicit((Object)(object)s.Attach))
			{
				return Fail(s, "RightHand_Attach");
			}
			s.HasWritten = false;
			return true;
		}

		private static bool Fail(State s, string bone)
		{
			s.Broken = true;
			Plugin.Log.LogWarning((object)("iai stance: player bone '" + bone + "' not found, the stance is off for this player"));
			return false;
		}

		private static Transform Find(Transform parent, string name)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if (((Object)parent).name == name)
			{
				return parent;
			}
			foreach (Transform item in parent)
			{
				Transform val = Find(item, name);
				if (Object.op_Implicit((Object)(object)val))
				{
					return val;
				}
			}
			return null;
		}

		private static bool Same(Quaternion a, Quaternion b)
		{
			//IL_0000: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (a.x == b.x && a.y == b.y && a.z == b.z)
			{
				return a.w == b.w;
			}
			return false;
		}
	}
	internal static class ImpactFrame
	{
		private static readonly FieldRef<CameraEffects, PostProcessingBehaviour> PostProcessing = AccessTools.FieldRefAccess<CameraEffects, PostProcessingBehaviour>("m_postProcessing");

		private const float ShakeRange = 10f;

		private const int InkWidth = 640;

		private const float CutAngle = 10f;

		private const int InkSoftness = 1;

		private const float FocusRadius = 0.4f;

		private const int SpeedLines = 96;

		private static readonly Color32 Ink = new Color32((byte)14, (byte)12, (byte)12, byte.MaxValue);

		private static readonly Color32 Paper = new Color32((byte)242, (byte)238, (byte)228, byte.MaxValue);

		private static ColorGradingModel _grading;

		private static Settings _saved;

		private static bool _savedEnabled;

		private static bool _flashing;

		private static int _flashId;

		private static bool _warnedFlash;

		private static readonly HashSet<string> WarnedSounds = new HashSet<string>();

		private const float CrashFade = 0.3f;

		private static RawImage _ink;

		private static Image _white;

		private static RenderTexture _grabTarget;

		private static Texture2D _grab;

		private static Texture2D _inkPicture;

		private static int _inkId;

		private static int _whiteId;

		private const float ClickSeconds = 0.12f;

		internal static float InkHides
		{
			get
			{
				if (!Plugin.ImpactEnabled.Value || !Plugin.ImpactInk.Value || !(Plugin.ImpactInkSeconds.Value > 0f))
				{
					return 0f;
				}
				return Plugin.ImpactInkSeconds.Value + 0.03f;
			}
		}

		internal static void Play(Vector3 point)
		{
			//IL_0059: 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 (Plugin.ImpactEnabled.Value)
			{
				if (Plugin.ImpactInk.Value && Plugin.ImpactInkSeconds.Value > 0f)
				{
					((MonoBehaviour)Plugin.Instance).StartCoroutine(InkFrame(++_inkId, point));
				}
				else
				{
					WhiteFlash();
				}
				Flash();
				Shake();
				Sound(point);
			}
		}

		private static void EnsureOverlay()
		{
			//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_0029: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0065: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_ink) || !Object.op_Implicit((Object)(object)_white))
			{
				GameObject val = new GameObject("IaidoKatana_impact_frame");
				Object.DontDestroyOnLoad((Object)val);
				Canvas obj = val.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 32000;
				_ink = FullScreen<RawImage>(val, "ink");
				((Behaviour)_ink).enabled = false;
				_white = FullScreen<Image>(val, "flash");
				((Graphic)_white).color = new Color(1f, 1f, 1f, 0f);
			}
		}

		private static T FullScreen<T>(GameObject root, string name) where T : Graphic
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			T val = new GameObject(name, new Type[1] { typeof(RectTransform) }).AddComponent<T>();
			((Component)(object)val).transform.SetParent(root.transform, false);
			((Graphic)val).rectTransform.anchorMin = Vector2.zero;
			((Graphic)val).rectTransform.anchorMax = Vector2.one;
			((Graphic)val).rectTransform.offsetMin = Vector2.zero;
			((Graphic)val).rectTransform.offsetMax = Vector2.zero;
			((Graphic)val).raycastTarget = false;
			return val;
		}

		private static IEnumerator InkFrame(int id, Vector3 point)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			EnsureOverlay();
			yield return null;
			yield return (object)new WaitForEndOfFrame();
			Camera main = Camera.main;
			if (id != _inkId || !Object.op_Implicit((Object)(object)main))
			{
				WhiteFlash();
				yield break;
			}
			int num = 640;
			int num2 = Mathf.Max(1, Mathf.RoundToInt((float)num * (float)Screen.height / (float)Mathf.Max(1, Screen.width)));
			if (!Object.op_Implicit((Object)(object)_grab) || ((Texture)_grab).width != num || ((Texture)_grab).height != num2)
			{
				if (Object.op_Implicit((Object)(object)_grabTarget))
				{
					_grabTarget.Release();
				}
				_grabTarget = new RenderTexture(num, num2, 24)
				{
					name = "IaidoKatana_ink_grab"
				};
				_grab = new Texture2D(num, num2, (TextureFormat)3, false)
				{
					name = "IaidoKatana_ink_read"
				};
				_inkPicture = new Texture2D(num, num2, (TextureFormat)4, false)
				{
					name = "IaidoKatana_ink",
					filterMode = (FilterMode)0
				};
			}
			RenderTexture targetTexture = main.targetTexture;
			RenderTexture active = RenderTexture.active;
			try
			{
				main.targetTexture = _grabTarget;
				main.Render();
				RenderTexture.active = _grabTarget;
				_grab.ReadPixels(new Rect(0f, 0f, (float)num, (float)num2), 0, 0, false);
			}
			finally
			{
				main.targetTexture = targetTexture;
				RenderTexture.active = active;
			}
			Color32[] pixels = _grab.GetPixels32();
			Vector3 val = main.WorldToScreenPoint(point);
			Vector2 cut = ((val.z > 0f && Plugin.ImpactInkCut.Value) ? new Vector2(val.x / (float)Mathf.Max(1, Screen.width) * (float)num, val.y / (float)Mathf.Max(1, Screen.height) * (float)num2) : new Vector2(-1f, -1f));
			Inkify(pixels, num, num2, cut, Plugin.ImpactInkInvert.Value);
			_inkPicture.SetPixels32(pixels);
			_inkPicture.Apply(false);
			_ink.texture = (Texture)(object)_inkPicture;
			((Behaviour)_ink).enabled = true;
			float end = Time.unscaledTime + Plugin.ImpactInkSeconds.Value;
			while (Time.unscaledTime < end && id == _inkId)
			{
				yield return null;
			}
			if (id == _inkId)
			{
				((Behaviour)_ink).enabled = false;
				WhiteFlash();
			}
		}

		internal static void Inkify(Color32[] pixels, int w, int h, Vector2 cut, bool invert)
		{
			//IL_0011: 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_001b: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_0075: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: 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_02d3: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: 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_02ad: Unknown result type (might be due to invalid IL or missing references)
			byte[] array = new byte[pixels.Length];
			for (int i = 0; i < pixels.Length; i++)
			{
				Color32 val = pixels[i];
				array[i] = (byte)(val.r * 77 + val.g * 150 + val.b * 29 >> 8);
			}
			Blur(array, w, h, 1);
			Vector2 val2 = (Vector2)((cut.x >= 0f) ? cut : new Vector2((float)w * 0.5f, (float)h * 0.5f));
			float num = (float)Math.Sqrt(w * w + h * h) * 0.5f;
			int[] array2 = new int[256];
			int num2 = 0;
			for (int j = 0; j < h; j++)
			{
				for (int k = 0; k < w; k++)
				{
					if (Distance(k, j, val2) / num < 0.4f)
					{
						array2[array[j * w + k]]++;
						num2++;
					}
				}
			}
			int num3 = 128;
			int l = 0;
			int num4 = 0;
			for (; l < 256; l++)
			{
				if (num2 <= 0)
				{
					break;
				}
				num4 += array2[l];
				if (num4 >= num2 / 2)
				{
					num3 = l;
					break;
				}
			}
			for (int m = 0; m < h; m++)
			{
				for (int n = 0; n < w; n++)
				{
					int num5 = m * w + n;
					float num6 = Distance(n, m, val2) / num;
					float num7 = Smooth(0.4f, 0.85f, num6) * 255f;
					bool flag = (float)(int)array[num5] + num7 > (float)num3 != invert;
					if (flag && SpeedLine((float)n - val2.x, (float)m - val2.y, num6))
					{
						flag = false;
					}
					pixels[num5] = (flag ? Paper : Ink);
				}
			}
			if (cut.x < 0f)
			{
				return;
			}
			float num8 = (float)Math.Tan(Math.PI / 18.0);
			float num9 = (float)w * 0.45f;
			float num10 = Mathf.Max(2f, (float)h * 0.014f);
			for (int num11 = Mathf.Max(0, (int)(cut.x - num9)); num11 < Mathf.Min(w, (int)(cut.x + num9)); num11++)
			{
				float num12 = Mathf.Abs((float)num11 - cut.x) / num9;
				float num13 = num10 * (float)Math.Pow(1f - num12, 0.699999988079071);
				float num14 = cut.y + ((float)num11 - cut.x) * num8;
				for (int num15 = Mathf.Max(0, (int)(num14 - num13)); num15 <= Mathf.Min(h - 1, (int)(num14 + num13)); num15++)
				{
					int num16 = num15 * w + num11;
					pixels[num16] = ((pixels[num16].r > 128) ? Ink : Paper);
				}
			}
		}

		private static float Distance(int x, int y, Vector2 p)
		{
			//IL_0002: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return (float)Math.Sqrt(((float)x - p.x) * ((float)x - p.x) + ((float)y - p.y) * ((float)y - p.y));
		}

		private static float Smooth(float from, float to, float v)
		{
			float num = Mathf.Clamp01((v - from) / (to - from));
			return num * num * (3f - 2f * num);
		}

		private static bool SpeedLine(float dx, float dy, float d)
		{
			if (d < 0.32000002f)
			{
				return false;
			}
			double num = Math.Atan2(dy, dx) + Math.PI;
			double num2 = Math.PI / 48.0;
			int num3 = (int)Math.Round(num / num2) % 96;
			uint num4 = (uint)(num3 * -1640531535);
			float num5 = (float)((num4 >> 8) & 0xFF) / 255f - 0.5f;
			float num6 = 0.32000002f + (float)((num4 >> 16) & 0xFF) / 255f * 0.35f;
			float num7 = 0.0025f + (float)((num4 >> 24) & 0xFF) / 255f * 0.006f;
			if (d < num6 || ((num4 >> 4) & 3) == 0)
			{
				return false;
			}
			double num8 = ((double)num3 + (double)num5 * 0.6) * num2;
			double num9 = Math.Abs(num - num8);
			if (num9 > Math.PI)
			{
				num9 = Math.PI * 2.0 - num9;
			}
			return num9 < (double)(num7 * (0.6f + (d - num6) * 2.5f));
		}

		private static void Blur(byte[] values, int w, int h, int r)
		{
			if (r <= 0)
			{
				return;
			}
			byte[] array = new byte[values.Length];
			for (int i = 0; i < h; i++)
			{
				int num = i * w;
				int num2 = 0;
				int num3 = 0;
				for (int j = -r; j < w; j++)
				{
					if (j + r < w)
					{
						num2 += values[num + j + r];
						num3++;
					}
					if (j - r - 1 >= 0)
					{
						num2 -= values[num + j - r - 1];
						num3--;
					}
					if (j >= 0)
					{
						array[num + j] = (byte)(num2 / num3);
					}
				}
			}
			for (int k = 0; k < w; k++)
			{
				int num4 = 0;
				int num5 =