Decompiled source of QuickHolster v1.0.0

Mods/QuickHolster.dll

Decompiled 7 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BoneLib;
using BoneLib.BoneMenu;
using Il2CppSLZ.Marrow;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using QuickHolster;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(QuickHolsterMod), "QuickHolster", "1.0.0", "nontendo", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("QuickHolster")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("QuickHolster")]
[assembly: AssemblyTitle("QuickHolster")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace QuickHolster
{
	public static class HolsterManager
	{
		private static MelonPreferences_Category _cat = null;

		private static MelonPreferences_Entry<bool> _pEnabled = null;

		private static MelonPreferences_Entry<bool> _pDebugLogging = null;

		private static MelonPreferences_Entry<float> _pCR = null;

		private static MelonPreferences_Entry<float> _pCD = null;

		private static MelonPreferences_Entry<float> _pCF = null;

		private static MelonPreferences_Entry<float> _pCX = null;

		private static MelonPreferences_Entry<float> _pCY = null;

		private static MelonPreferences_Entry<float> _pCZ = null;

		private static MelonPreferences_Entry<float> _pTR = null;

		private static MelonPreferences_Entry<float> _pTD = null;

		private static MelonPreferences_Entry<float> _pTF = null;

		private static MelonPreferences_Entry<float> _pTX = null;

		private static MelonPreferences_Entry<float> _pTY = null;

		private static MelonPreferences_Entry<float> _pTZ = null;

		public static readonly HolsterSlot Chest = new HolsterSlot("Chest", 0f, 0f, 0f, 0f, -90f, 0f);

		public static readonly HolsterSlot Thigh = new HolsterSlot("Thigh", 0.25f, -0.1f, 0.05f, 0f, 0f, 0f, useBodyAnchor: true);

		private static bool _initialized;

		private static float _debugTimer;

		private static Transform? _cachedPelvis;

		public static bool Enabled
		{
			get
			{
				return _pEnabled.Value;
			}
			set
			{
				_pEnabled.Value = value;
				Save();
			}
		}

		public static bool DebugLogging
		{
			get
			{
				return _pDebugLogging.Value;
			}
			set
			{
				_pDebugLogging.Value = value;
				Save();
			}
		}

		public static void InitPreferences()
		{
			_cat = MelonPreferences.CreateCategory("QuickHolster");
			_pEnabled = _cat.CreateEntry<bool>("Enabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pDebugLogging = _cat.CreateEntry<bool>("DebugLogging", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pCR = _cat.CreateEntry<float>("ChestRight", Chest.OffsetRight, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pCD = _cat.CreateEntry<float>("ChestDown", Chest.OffsetDown, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pCF = _cat.CreateEntry<float>("ChestForward", Chest.OffsetForward, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pCX = _cat.CreateEntry<float>("ChestRotX", Chest.RotX, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pCY = _cat.CreateEntry<float>("ChestRotY", Chest.RotY, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pCZ = _cat.CreateEntry<float>("ChestRotZ", Chest.RotZ, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pTR = _cat.CreateEntry<float>("ThighRight", Thigh.OffsetRight, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pTD = _cat.CreateEntry<float>("ThighDown", Thigh.OffsetDown, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pTF = _cat.CreateEntry<float>("ThighForward", Thigh.OffsetForward, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pTX = _cat.CreateEntry<float>("ThighRotX", Thigh.RotX, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pTY = _cat.CreateEntry<float>("ThighRotY", Thigh.RotY, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_pTZ = _cat.CreateEntry<float>("ThighRotZ", Thigh.RotZ, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			Chest.OffsetRight = _pCR.Value;
			Chest.OffsetDown = _pCD.Value;
			Chest.OffsetForward = _pCF.Value;
			Chest.RotX = _pCX.Value;
			Chest.RotY = _pCY.Value;
			Chest.RotZ = _pCZ.Value;
			Thigh.OffsetRight = _pTR.Value;
			Thigh.OffsetDown = _pTD.Value;
			Thigh.OffsetForward = _pTF.Value;
			Thigh.RotX = _pTX.Value;
			Thigh.RotY = _pTY.Value;
			Thigh.RotZ = _pTZ.Value;
		}

		public static void SaveSlots()
		{
			_pCR.Value = Chest.OffsetRight;
			_pCD.Value = Chest.OffsetDown;
			_pCF.Value = Chest.OffsetForward;
			_pCX.Value = Chest.RotX;
			_pCY.Value = Chest.RotY;
			_pCZ.Value = Chest.RotZ;
			_pTR.Value = Thigh.OffsetRight;
			_pTD.Value = Thigh.OffsetDown;
			_pTF.Value = Thigh.OffsetForward;
			_pTX.Value = Thigh.RotX;
			_pTY.Value = Thigh.RotY;
			_pTZ.Value = Thigh.RotZ;
			Save();
		}

		private static void Save()
		{
			_cat.SaveToFile(false);
		}

		public static void OnLevelLoaded()
		{
			Chest.Detach(destroy: true);
			Thigh.Detach(destroy: true);
			_cachedPelvis = null;
			_initialized = false;
		}

		public static void OnUpdate()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_008e: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			if (!Enabled)
			{
				return;
			}
			try
			{
				if (!EnsureInit())
				{
					return;
				}
				RigManager rigManager = Player.RigManager;
				if ((Object)(object)((rigManager != null) ? rigManager.physicsRig : null) == (Object)null)
				{
					return;
				}
				Hand leftHand = rigManager.physicsRig.leftHand;
				Hand rightHand = rigManager.physicsRig.rightHand;
				if ((Object)(object)leftHand == (Object)null || (Object)(object)rightHand == (Object)null)
				{
					return;
				}
				Vector3 worldPos = GetWorldPos(Chest);
				Vector3 worldPos2 = GetWorldPos(Thigh);
				Chest.Tick(leftHand, rightHand, worldPos);
				Thigh.Tick(leftHand, rightHand, worldPos2);
				if (DebugLogging)
				{
					_debugTimer -= Time.deltaTime;
					if (_debugTimer <= 0f)
					{
						_debugTimer = 1f;
						GameObject currentAttachedGO = leftHand.m_CurrentAttachedGO;
						GameObject currentAttachedGO2 = rightHand.m_CurrentAttachedGO;
						float value = (((Object)(object)currentAttachedGO != (Object)null) ? Vector3.Distance(((Component)leftHand).transform.position, worldPos) : (-1f));
						float value2 = (((Object)(object)currentAttachedGO2 != (Object)null) ? Vector3.Distance(((Component)rightHand).transform.position, worldPos) : (-1f));
						MelonLogger.Msg($"[QuickHolster] chest={worldPos:F2} thigh={worldPos2:F2} L=({((currentAttachedGO != null) ? ((Object)currentAttachedGO).name : null) ?? "empty"},d={value:F2}) R=({((currentAttachedGO2 != null) ? ((Object)currentAttachedGO2).name : null) ?? "empty"},d={value2:F2}) chestFull={Chest.IsHolstered} thighFull={Thigh.IsHolstered}");
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[QuickHolster] " + ex);
			}
		}

		public static Vector3 GetWorldPos(HolsterSlot slot)
		{
			//IL_0069: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_004d: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position;
			Vector3 forward;
			if (slot.UseBodyAnchor)
			{
				Transform pelvis = GetPelvis();
				if ((Object)(object)pelvis != (Object)null)
				{
					position = pelvis.position;
					forward = pelvis.forward;
				}
				else
				{
					Transform head = Player.Head;
					if ((Object)(object)head == (Object)null)
					{
						return Vector3.zero;
					}
					position = head.position;
					forward = head.forward;
				}
			}
			else
			{
				Transform head2 = Player.Head;
				if ((Object)(object)head2 == (Object)null)
				{
					return Vector3.zero;
				}
				position = head2.position;
				forward = head2.forward;
			}
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
			{
				forward = Vector3.forward;
			}
			else
			{
				((Vector3)(ref forward)).Normalize();
			}
			Vector3 val = Vector3.Cross(Vector3.up, forward);
			return position + val * slot.OffsetRight + Vector3.up * slot.OffsetDown + forward * slot.OffsetForward;
		}

		public static Quaternion GetWorldRot(HolsterSlot slot)
		{
			//IL_0047: 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_002f: 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_0034: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val2;
			if (slot.UseBodyAnchor)
			{
				Transform pelvis = GetPelvis();
				? val;
				if (!((Object)(object)pelvis != (Object)null))
				{
					Transform head = Player.Head;
					val = ((head != null) ? head.forward : Vector3.forward);
				}
				else
				{
					val = pelvis.forward;
				}
				val2 = (Vector3)val;
			}
			else
			{
				Transform head2 = Player.Head;
				val2 = ((head2 != null) ? head2.forward : Vector3.forward);
			}
			val2.y = 0f;
			return ((((Vector3)(ref val2)).sqrMagnitude > 0.01f) ? Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up) : Quaternion.identity) * Quaternion.Euler(slot.RotX, slot.RotY, slot.RotZ);
		}

		private static Transform? GetPelvis()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_cachedPelvis != (Object)null)
			{
				try
				{
					_ = _cachedPelvis.position;
					return _cachedPelvis;
				}
				catch
				{
					_cachedPelvis = null;
				}
			}
			try
			{
				RigManager rigManager = Player.RigManager;
				PhysicsRig val = ((rigManager != null) ? rigManager.physicsRig : null);
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				Type type = ((object)val).GetType();
				string[] array = new string[6] { "m_pelvis", "pelvis", "m_hip", "hip", "pelvisTF", "m_pelvisTF" };
				foreach (string name in array)
				{
					object? obj2 = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public)?.GetValue(val);
					Transform val2 = (Transform)((obj2 is Transform) ? obj2 : null);
					if (val2 != null)
					{
						_cachedPelvis = val2;
						return val2;
					}
					object? obj3 = type.GetField(name, BindingFlags.Instance | BindingFlags.Public)?.GetValue(val);
					Transform val3 = (Transform)((obj3 is Transform) ? obj3 : null);
					if (val3 != null)
					{
						_cachedPelvis = val3;
						return val3;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		public static bool IsGun(GameObject go)
		{
			try
			{
				if ((Object)(object)go.GetComponentInParent<Grip>() != (Object)null)
				{
					return true;
				}
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)go.GetComponent<Grip>() != (Object)null)
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool EnsureInit()
		{
			if (_initialized)
			{
				return true;
			}
			if (!Player.HandsExist)
			{
				return false;
			}
			Chest.InitGhost();
			Thigh.InitGhost();
			_initialized = true;
			MelonLogger.Msg("[QuickHolster] Initialized");
			return true;
		}
	}
	public class HolsterSlot
	{
		public readonly string Name;

		public readonly bool UseBodyAnchor;

		private const float ZoneRadius = 0.22f;

		public float OffsetRight;

		public float OffsetDown;

		public float OffsetForward;

		public float RotX;

		public float RotY;

		public float RotZ;

		private Rigidbody? _rb;

		private Transform? _xf;

		private Collider[]? _savedColliders;

		private GameObject? _primedGo;

		private Rigidbody? _primedRb;

		private bool _primedLeft;

		private bool _hasPrime;

		private GameObject? _ghostGo;

		private Material? _ghostMat;

		public bool IsHolstered => (Object)(object)_rb != (Object)null;

		public HolsterSlot(string name, float offsetRight, float offsetDown, float offsetForward, float rotX, float rotY, float rotZ, bool useBodyAnchor = false)
		{
			Name = name;
			UseBodyAnchor = useBodyAnchor;
			OffsetRight = offsetRight;
			OffsetDown = offsetDown;
			OffsetForward = offsetForward;
			RotX = rotX;
			RotY = rotY;
			RotZ = rotZ;
		}

		public void Tick(Hand left, Hand right, Vector3 pos)
		{
			//IL_0015: 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)
			if (IsHolstered)
			{
				TickHolstered(left, right, pos);
			}
			else
			{
				TickEmpty(left, right, pos);
			}
		}

		private void TickEmpty(Hand left, Hand right, Vector3 pos)
		{
			//IL_0001: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			ShowGhost(pos, HolsterManager.DebugLogging);
			TickHand(left, isLeft: true, pos);
			TickHand(right, isLeft: false, pos);
		}

		private void TickHand(Hand hand, bool isLeft, Vector3 pos)
		{
			//IL_0079: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			GameObject currentAttachedGO = hand.m_CurrentAttachedGO;
			if (_hasPrime && _primedLeft == isLeft && (Object)(object)_primedRb != (Object)null && (Object)(object)currentAttachedGO == (Object)null)
			{
				Snap(_primedGo, _primedRb, pos);
				ClearPrime();
			}
			else if ((Object)(object)currentAttachedGO == (Object)null)
			{
				if (_hasPrime && _primedLeft == isLeft)
				{
					ClearPrime();
				}
			}
			else
			{
				if (!HolsterManager.IsGun(currentAttachedGO))
				{
					return;
				}
				if (Vector3.Distance(((Component)hand).transform.position, pos) <= 0.22f)
				{
					_primedGo = currentAttachedGO;
					_primedRb = currentAttachedGO.GetComponent<Rigidbody>() ?? currentAttachedGO.GetComponentInParent<Rigidbody>();
					_primedLeft = isLeft;
					_hasPrime = true;
					if ((Object)(object)_ghostMat != (Object)null)
					{
						_ghostMat.color = new Color(0.2f, 1f, 0.4f, 0.6f);
					}
				}
				else if (_hasPrime && _primedLeft == isLeft && (Object)(object)_primedGo == (Object)(object)currentAttachedGO)
				{
					ClearPrime();
				}
			}
		}

		private void Snap(GameObject go, Rigidbody rb, Vector3 pos)
		{
			//IL_0076: 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_0091: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				List<Collider> list = new List<Collider>();
				foreach (Collider componentsInChild in ((Component)rb).gameObject.GetComponentsInChildren<Collider>(true))
				{
					try
					{
						if (!((Object)(object)componentsInChild == (Object)null) && !componentsInChild.isTrigger)
						{
							list.Add(componentsInChild);
							componentsInChild.enabled = false;
						}
					}
					catch
					{
					}
				}
				_savedColliders = list.ToArray();
				rb.isKinematic = true;
				rb.useGravity = false;
				rb.velocity = Vector3.zero;
				rb.angularVelocity = Vector3.zero;
				((Component)rb).transform.position = pos;
				((Component)rb).transform.rotation = HolsterManager.GetWorldRot(this);
				_rb = rb;
				_xf = ((Component)rb).transform;
				ShowGhost(pos, active: false);
				MelonLogger.Msg("[QuickHolster] " + Name + ": holstered " + ((Object)go).name);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[QuickHolster] " + Name + " snap failed: " + ex.Message);
				_rb = null;
				_xf = null;
			}
		}

		private void TickHolstered(Hand left, Hand right, Vector3 pos)
		{
			//IL_002b: 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_0048: 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)
			if ((Object)(object)_rb == (Object)null || (Object)(object)_xf == (Object)null)
			{
				Detach(destroy: false);
				return;
			}
			try
			{
				_xf.position = pos;
				_xf.rotation = HolsterManager.GetWorldRot(this);
				_rb.velocity = Vector3.zero;
				_rb.angularVelocity = Vector3.zero;
			}
			catch
			{
				Detach(destroy: false);
				return;
			}
			if (HandIsHolding(left, ((Component)_xf).gameObject) || HandIsHolding(right, ((Component)_xf).gameObject))
			{
				MelonLogger.Msg("[QuickHolster] " + Name + ": drawn!");
				Detach(destroy: false);
			}
		}

		private static bool HandIsHolding(Hand hand, GameObject root)
		{
			try
			{
				GameObject currentAttachedGO = hand.m_CurrentAttachedGO;
				if ((Object)(object)currentAttachedGO == (Object)null)
				{
					return false;
				}
				return (Object)(object)currentAttachedGO == (Object)(object)root || currentAttachedGO.transform.IsChildOf(root.transform) || root.transform.IsChildOf(currentAttachedGO.transform);
			}
			catch
			{
				return false;
			}
		}

		public void Detach(bool destroy)
		{
			if ((Object)(object)_rb != (Object)null)
			{
				try
				{
					_rb.isKinematic = false;
					_rb.useGravity = true;
				}
				catch
				{
				}
			}
			if (_savedColliders != null)
			{
				Collider[] savedColliders = _savedColliders;
				foreach (Collider val in savedColliders)
				{
					try
					{
						if ((Object)(object)val != (Object)null)
						{
							val.enabled = true;
						}
					}
					catch
					{
					}
				}
			}
			_savedColliders = null;
			_rb = null;
			_xf = null;
			if (!destroy)
			{
				return;
			}
			if ((Object)(object)_ghostGo != (Object)null)
			{
				try
				{
					Object.Destroy((Object)(object)_ghostGo);
				}
				catch
				{
				}
			}
			_ghostGo = null;
			_ghostMat = null;
		}

		private void ClearPrime()
		{
			_primedGo = null;
			_primedRb = null;
			_hasPrime = false;
		}

		private void ShowGhost(Vector3 pos, bool active)
		{
			//IL_002c: 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)
			if ((Object)(object)_ghostGo == (Object)null)
			{
				return;
			}
			try
			{
				_ghostGo.SetActive(active);
				if (active)
				{
					_ghostGo.transform.position = pos;
					if ((Object)(object)_ghostMat != (Object)null)
					{
						float num = 0.45f + 0.25f * Mathf.Sin(Time.time * 2.5f);
						_ghostMat.color = new Color(0.4f, 0.8f, 1f, num);
					}
				}
			}
			catch
			{
			}
		}

		public void InitGhost()
		{
			//IL_0042: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_ghostGo = GameObject.CreatePrimitive((PrimitiveType)0);
				Object.DontDestroyOnLoad((Object)(object)_ghostGo);
				((Object)_ghostGo).name = "[QuickHolster] Ghost (" + Name + ")";
				_ghostGo.transform.localScale = Vector3.one * 0.12f;
				SphereCollider component = _ghostGo.GetComponent<SphereCollider>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				MeshRenderer component2 = _ghostGo.GetComponent<MeshRenderer>();
				Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("UI/Default") ?? Shader.Find("Standard");
				if ((Object)(object)val != (Object)null && (Object)(object)component2 != (Object)null)
				{
					_ghostMat = new Material(val);
					if (((Object)val).name == "Standard")
					{
						_ghostMat.SetFloat("_Mode", 3f);
						_ghostMat.SetInt("_SrcBlend", 5);
						_ghostMat.SetInt("_DstBlend", 10);
						_ghostMat.DisableKeyword("_ALPHATEST_ON");
						_ghostMat.EnableKeyword("_ALPHABLEND_ON");
						_ghostMat.DisableKeyword("_ALPHAPREMULTIPLY_ON");
					}
					_ghostMat.color = new Color(0.4f, 0.8f, 1f, 0.6f);
					_ghostMat.SetInt("_ZTest", 8);
					_ghostMat.SetInt("_ZWrite", 0);
					_ghostMat.renderQueue = 4000;
					((Renderer)component2).material = _ghostMat;
				}
				_ghostGo.SetActive(false);
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[QuickHolster] " + Name + " ghost init: " + ex.Message);
				_ghostGo = null;
			}
		}
	}
	public class QuickHolsterMod : MelonMod
	{
		public override void OnInitializeMelon()
		{
			HolsterManager.InitPreferences();
			Hooking.OnLevelLoaded += delegate
			{
				HolsterManager.OnLevelLoaded();
			};
			SetupMenu();
			((MelonBase)this).LoggerInstance.Msg("QuickHolster loaded!");
		}

		private static void SetupMenu()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			Page obj = GetOrCreateQuickModsPage().CreatePage("QuickHolster", new Color(0.75f, 0.55f, 0.25f), 0, true);
			obj.CreateBool("Enabled", Color.white, HolsterManager.Enabled, (Action<bool>)delegate(bool v)
			{
				HolsterManager.Enabled = v;
			});
			obj.CreateBool("Debug Mode", Color.yellow, HolsterManager.DebugLogging, (Action<bool>)delegate(bool v)
			{
				HolsterManager.DebugLogging = v;
			});
			AddSlotPage(obj, "Chest Holster", HolsterManager.Chest);
			AddSlotPage(obj, "Thigh Holster", HolsterManager.Thigh);
		}

		private static void AddSlotPage(Page parent, string title, HolsterSlot slot)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			Page obj = parent.CreatePage(title, Color.white, 0, true);
			Page obj2 = obj.CreatePage("Position", Color.white, 0, true);
			obj2.CreateFloat("Right Offset", Color.white, slot.OffsetRight, 0.01f, -0.4f, 0.4f, (Action<float>)delegate(float v)
			{
				slot.OffsetRight = v;
				HolsterManager.SaveSlots();
			});
			obj2.CreateFloat("Down Offset", Color.white, slot.OffsetDown, 0.01f, -0.8f, 0.2f, (Action<float>)delegate(float v)
			{
				slot.OffsetDown = v;
				HolsterManager.SaveSlots();
			});
			obj2.CreateFloat("Forward Offset", Color.white, slot.OffsetForward, 0.01f, -0.2f, 0.3f, (Action<float>)delegate(float v)
			{
				slot.OffsetForward = v;
				HolsterManager.SaveSlots();
			});
			Page obj3 = obj.CreatePage("Rotation", Color.white, 0, true);
			obj3.CreateFloat("Tilt (X)", Color.white, slot.RotX, 5f, -180f, 180f, (Action<float>)delegate(float v)
			{
				slot.RotX = v;
				HolsterManager.SaveSlots();
			});
			obj3.CreateFloat("Turn (Y)", Color.white, slot.RotY, 5f, -180f, 180f, (Action<float>)delegate(float v)
			{
				slot.RotY = v;
				HolsterManager.SaveSlots();
			});
			obj3.CreateFloat("Roll (Z)", Color.white, slot.RotZ, 5f, -180f, 180f, (Action<float>)delegate(float v)
			{
				slot.RotZ = v;
				HolsterManager.SaveSlots();
			});
		}

		private static Page GetOrCreateQuickModsPage()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			object? data = AppDomain.CurrentDomain.GetData("QuickMods.RootPage");
			Page val = (Page)((data is Page) ? data : null);
			if (val != null)
			{
				return val;
			}
			Page val2 = Page.Root.CreatePage("Quick Mods", new Color(0.35f, 0.27f, 0.9f), 0, true);
			AppDomain.CurrentDomain.SetData("QuickMods.RootPage", val2);
			return val2;
		}

		public override void OnUpdate()
		{
			HolsterManager.OnUpdate();
		}
	}
}