Decompiled source of MagSlide V2 v1.1.0

Mods/MagSlideV2.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.Notifications;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Data;
using Il2CppSLZ.Marrow.Pool;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using MagSlide;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Mod), "MagSlide V2", "1.1.0", "JK", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("JK")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("JK 2026")]
[assembly: AssemblyDescription("Realistic magazine sliding for BONELAB")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("MagSlide V2")]
[assembly: AssemblyTitle("MagSlide V2")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MagSlide
{
	internal static class Builtins
	{
		internal enum Kind
		{
			None,
			OwnHold,
			OwnSlide
		}

		private sealed class Found
		{
			public Kind Kind;

			public string Name;

			public string How;

			public bool Inherit;
		}

		private static readonly string[] SlideParts = new string[4] { "slide_system", "joint_maker", "gunlatcher", "hand_ignorer" };

		private const float TakenWithin = 0.15f;

		private const float StillSqueezing = 0.5f;

		private static readonly Dictionary<string, Found> _guns = new Dictionary<string, Found>();

		private static readonly Dictionary<int, bool> _mags = new Dictionary<int, bool>();

		internal static bool On
		{
			get
			{
				if (Prefs.Detect != null)
				{
					return Prefs.Detect.Value;
				}
				return true;
			}
		}

		internal static void Prime(Well w)
		{
			w.ModelPrimed = true;
			try
			{
				w.ModelKey = KeyOf(w.Socket, out var name);
				w.ModelName = name;
			}
			catch
			{
			}
			if (On && w.ModelKey != null)
			{
				if (_guns.TryGetValue(w.ModelKey, out var value) && value.Inherit)
				{
					Apply(w, value.Kind, learned: true);
				}
				if (w.ForeignSystem && !w.ForeignByDetect)
				{
					Record(w, Kind.OwnSlide, "its mag well's normal catch is switched off", inherit: false);
				}
				else if ((Object)(object)w.Trigger == (Object)null)
				{
					Record(w, Kind.OwnSlide, "its mag well has no normal catch", inherit: false);
				}
			}
		}

		private static string KeyOf(AmmoSocket s, out string name)
		{
			name = null;
			try
			{
				Poolee componentInParent = ((Component)s).GetComponentInParent<Poolee>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					name = CleanName(((Object)componentInParent).name);
					SpawnableCrate spawnableCrate = componentInParent.SpawnableCrate;
					Barcode val = (((Object)(object)spawnableCrate == (Object)null) ? null : ((Scannable)spawnableCrate).Barcode);
					string text = ((val == (Barcode)null) ? null : val.ID);
					if (!string.IsNullOrEmpty(text))
					{
						try
						{
							string text2 = StripTags(((Scannable)spawnableCrate).Title);
							if (!string.IsNullOrEmpty(text2))
							{
								name = text2;
							}
						}
						catch
						{
						}
						return text;
					}
				}
			}
			catch
			{
			}
			if (string.IsNullOrEmpty(name))
			{
				try
				{
					Gun gun = s.gun;
					if ((Object)(object)gun != (Object)null)
					{
						name = CleanName(((Object)gun).name);
					}
				}
				catch
				{
				}
			}
			if (string.IsNullOrEmpty(name))
			{
				name = CleanName(Names.Of((Component)(object)s));
			}
			if (!string.IsNullOrEmpty(name))
			{
				return "name:" + name;
			}
			return null;
		}

		internal static string CleanName(string n)
		{
			if (string.IsNullOrEmpty(n))
			{
				return n;
			}
			n = n.Replace("(Clone)", "");
			int num = n.LastIndexOf(" [", StringComparison.Ordinal);
			if (num > 0 && n.EndsWith("]", StringComparison.Ordinal))
			{
				n = n.Substring(0, num);
			}
			return n.Trim();
		}

		private static string StripTags(string s)
		{
			if (string.IsNullOrEmpty(s))
			{
				return s;
			}
			StringBuilder stringBuilder = new StringBuilder(s.Length);
			bool flag = false;
			foreach (char c in s)
			{
				switch (c)
				{
				case '<':
					flag = true;
					continue;
				case '>':
					flag = false;
					continue;
				}
				if (!flag)
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString().Trim();
		}

		private static Transform RootOf(Well w)
		{
			try
			{
				Poolee componentInParent = ((Component)w.Socket).GetComponentInParent<Poolee>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					return ((Component)componentInParent).transform;
				}
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)w.GunRb != (Object)null && !Geom.IsRigBody(w.GunRb))
				{
					return ((Component)w.GunRb).transform;
				}
			}
			catch
			{
			}
			return null;
		}

		private static Transform FindPart(Transform root, string[] parts)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			try
			{
				Il2CppArrayBase<Transform> componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
				if (componentsInChildren == null)
				{
					return null;
				}
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Transform val = componentsInChildren[i];
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					string name = ((Object)val).name;
					if (string.IsNullOrEmpty(name))
					{
						continue;
					}
					name = name.ToLowerInvariant();
					for (int j = 0; j < parts.Length; j++)
					{
						if (name.Contains(parts[j]))
						{
							return val;
						}
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static Transform FindHoldPart(Transform root, Transform skip)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			try
			{
				HashSet<IntPtr> hashSet = null;
				if ((Object)(object)skip != (Object)null)
				{
					hashSet = new HashSet<IntPtr>();
					Il2CppArrayBase<Transform> componentsInChildren = ((Component)skip).GetComponentsInChildren<Transform>(true);
					if (componentsInChildren != null)
					{
						for (int i = 0; i < componentsInChildren.Length; i++)
						{
							if ((Object)(object)componentsInChildren[i] != (Object)null)
							{
								hashSet.Add(((Il2CppObjectBase)componentsInChildren[i]).Pointer);
							}
						}
					}
				}
				Transform val = null;
				Il2CppArrayBase<Transform> componentsInChildren2 = ((Component)root).GetComponentsInChildren<Transform>(true);
				if (componentsInChildren2 == null)
				{
					return null;
				}
				for (int j = 0; j < componentsInChildren2.Length; j++)
				{
					Transform val2 = componentsInChildren2[j];
					if ((Object)(object)val2 == (Object)null || (hashSet != null && hashSet.Contains(((Il2CppObjectBase)val2).Pointer)))
					{
						continue;
					}
					string name = ((Object)val2).name;
					if (string.IsNullOrEmpty(name))
					{
						continue;
					}
					name = name.ToLowerInvariant();
					if (!name.Contains("magholder"))
					{
						if (name.StartsWith("maghold", StringComparison.Ordinal))
						{
							return val2;
						}
						if ((Object)(object)val == (Object)null && (name.Contains("maghold") || name.Contains("mag hold") || name.Contains("mag_hold")))
						{
							val = val2;
						}
					}
				}
				return val;
			}
			catch
			{
				return null;
			}
		}

		internal static bool MagHasOwnSlide(Magazine mag, int plugId)
		{
			if (!On || (Object)(object)mag == (Object)null)
			{
				return false;
			}
			if (_mags.TryGetValue(plugId, out var value))
			{
				return value;
			}
			Transform val = null;
			try
			{
				Poolee componentInParent = ((Component)mag).GetComponentInParent<Poolee>();
				val = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).transform : ((Component)mag).transform);
			}
			catch
			{
			}
			value = (Object)(object)FindPart(val, SlideParts) != (Object)null;
			if (_mags.Count > 512)
			{
				_mags.Clear();
			}
			_mags[plugId] = value;
			if (value)
			{
				string text = "?";
				try
				{
					text = CleanName(((Object)(object)val != (Object)null) ? ((Object)val).name : ((Object)mag).name);
				}
				catch
				{
				}
				Record("mag:" + text, text + " (magazine)", Kind.OwnSlide, "it carries its own slide system", inherit: false);
				L.T("BUILT-IN mag '" + text + "' carries its own slide system: the rail leaves it to that");
			}
			return value;
		}

		internal static bool SeatedOwnSlide(Well w)
		{
			if (!On)
			{
				return false;
			}
			AmmoPlug plug;
			Magazine val = Wells.SeatedMag(w, out plug);
			if ((Object)(object)val == (Object)null || (Object)(object)plug == (Object)null)
			{
				return false;
			}
			int plugId = 0;
			try
			{
				plugId = ((Object)plug).GetInstanceID();
			}
			catch
			{
			}
			return MagHasOwnSlide(val, plugId);
		}

		internal static bool OwnHoldNow(Well w)
		{
			if (!On || w == null)
			{
				return false;
			}
			if (w.OwnHoldLearned)
			{
				return true;
			}
			if (!w.HoldScanned)
			{
				w.HoldScanned = true;
				AmmoPlug plug;
				Magazine val = Wells.SeatedMag(w, out plug);
				Transform skip = null;
				try
				{
					if ((Object)(object)val != (Object)null && val.isMagazineInserted)
					{
						skip = ((Component)val).transform;
					}
				}
				catch
				{
				}
				w.HoldPart = FindHoldPart(RootOf(w), skip);
				if ((Object)(object)w.HoldPart != (Object)null)
				{
					string text = "?";
					try
					{
						text = ((Object)w.HoldPart).name;
					}
					catch
					{
					}
					Learn(w, Kind.OwnHold, "it has a mag hold built in ('" + text + "')", inherit: false);
				}
			}
			if ((Object)(object)w.HoldPart == (Object)null)
			{
				return false;
			}
			try
			{
				return ((Component)w.HoldPart).gameObject.activeInHierarchy;
			}
			catch
			{
				w.HoldPart = null;
				return false;
			}
		}

		internal static bool HandTaken(Well w, Hand hand, float now)
		{
			if (!On || w == null || (Object)(object)hand == (Object)null)
			{
				return false;
			}
			float num = now - w.KeptSince;
			if (w.KeptSince <= 0f || num > 0.15f)
			{
				return false;
			}
			if (Grips.GripForce(hand) < 0.5f)
			{
				return false;
			}
			string text = Grips.AttachedName(hand);
			Learn(w, Kind.OwnHold, $"it took the hand off the keep {num * 1000f:F0} ms after the click" + ((text != null) ? (", now on '" + text + "'") : ""), inherit: true);
			return true;
		}

		internal static void Learn(Well w, Kind kind, string how, bool inherit)
		{
			if (w != null && kind != Kind.None)
			{
				if (!w.ModelPrimed)
				{
					Prime(w);
				}
				Apply(w, kind, inherit);
				Record(w, kind, how, inherit);
			}
		}

		private static void Record(Well w, Kind kind, string how, bool inherit)
		{
			string key = w.ModelKey ?? ("well:" + w.Id);
			string name = w.ModelName ?? CleanName(Names.Of((Component)(object)w.Socket));
			Record(key, name, kind, how, inherit);
		}

		private static void Record(string key, string name, Kind kind, string how, bool inherit)
		{
			if (_guns.TryGetValue(key, out var value) && value.Kind >= kind)
			{
				if (inherit)
				{
					value.Inherit = true;
				}
				return;
			}
			_guns[key] = new Found
			{
				Kind = kind,
				Name = name,
				How = how,
				Inherit = inherit
			};
			if (key.StartsWith("mag:", StringComparison.Ordinal))
			{
				L.M($"'{name}' has its own mag slide ({how}). The rail leaves it to that.");
				return;
			}
			L.M((kind == Kind.OwnSlide) ? $"'{name}' has its own mag slide ({how}). {"MagSlide V2"} leaves that gun's mag well alone." : $"'{name}' has its own mag hold ({how}). With your other hand on its trigger grip the gun holds your hand there; anywhere else, Keep Hand On Mag does.");
		}

		private static void Apply(Well w, Kind kind, bool learned)
		{
			if (kind == Kind.OwnSlide)
			{
				Wells.LeaveAlone(w, "the gun has its own mag slide", byDetect: true);
			}
			else if (kind == Kind.OwnHold && learned)
			{
				w.OwnHoldLearned = true;
			}
		}

		internal static string Describe(Well w)
		{
			if (w == null)
			{
				return "?";
			}
			if (w.ForeignSystem)
			{
				if (!w.ForeignByDetect)
				{
					return "own mag slide (no usable capture trigger)";
				}
				return "own mag slide (detected)";
			}
			if (w.OwnHoldLearned)
			{
				return "own mag hold (learned)";
			}
			if ((Object)(object)w.HoldPart != (Object)null)
			{
				bool flag = false;
				try
				{
					flag = ((Component)w.HoldPart).gameObject.activeInHierarchy;
				}
				catch
				{
				}
				if (!flag)
				{
					return "own mag hold (switched off on the gun)";
				}
				return "own mag hold";
			}
			if (!w.HoldScanned)
			{
				return "not checked yet";
			}
			return "none";
		}

		internal static string Summary()
		{
			List<string> list = new List<string>();
			List<string> list2 = new List<string>();
			foreach (KeyValuePair<string, Found> gun in _guns)
			{
				if (gun.Value.Kind == Kind.OwnSlide)
				{
					list.Add(gun.Value.Name);
				}
				else if (gun.Value.Kind == Kind.OwnHold)
				{
					list2.Add(gun.Value.Name);
				}
			}
			if (list.Count + list2.Count == 0)
			{
				if (!On)
				{
					return "Detection is off.";
				}
				return "No guns with their own mag slide or mag hold found yet. Grab one and load it.";
			}
			foreach (KeyValuePair<string, Found> gun2 in _guns)
			{
				L.M($"built-in: '{gun2.Value.Name}' {((gun2.Value.Kind == Kind.OwnSlide) ? "own mag slide" : "own mag hold")} ({gun2.Value.How})");
			}
			StringBuilder stringBuilder = new StringBuilder();
			if (list2.Count > 0)
			{
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder3 = stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(15, 1, stringBuilder2);
				handler.AppendLiteral("Own mag hold: ");
				handler.AppendFormatted(Few(list2));
				handler.AppendLiteral(".");
				stringBuilder3.Append(ref handler);
			}
			if (list.Count > 0)
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(' ');
				}
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder4 = stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(16, 1, stringBuilder2);
				handler.AppendLiteral("Own mag slide: ");
				handler.AppendFormatted(Few(list));
				handler.AppendLiteral(".");
				stringBuilder4.Append(ref handler);
			}
			return stringBuilder.ToString();
		}

		private static string Few(List<string> names)
		{
			names.Sort(StringComparer.OrdinalIgnoreCase);
			if (names.Count <= 4)
			{
				return string.Join(", ", names);
			}
			return string.Join(", ", names.GetRange(0, 4)) + $" and {names.Count - 4} more";
		}

		internal static void Forget()
		{
			_guns.Clear();
			_mags.Clear();
			Well[] array = Wells.Snapshot();
			foreach (Well well in array)
			{
				well.OwnHoldLearned = false;
				well.HoldScanned = false;
				well.HoldPart = null;
				if (well.ForeignByDetect)
				{
					well.ForeignByDetect = false;
					well.ForeignSystem = false;
				}
			}
		}

		internal static void ClearLevel()
		{
			_mags.Clear();
		}
	}
	internal static class ForcePulls
	{
		private const float FlightWindow = 1.5f;

		private const float LandGrace = 0.35f;

		private static readonly Dictionary<int, float> _pulledAt = new Dictionary<int, float>();

		private static readonly Dictionary<int, float> _landedAt = new Dictionary<int, float>();

		internal static void Scan()
		{
			try
			{
				Check(Player.LeftHand);
			}
			catch
			{
			}
			try
			{
				Check(Player.RightHand);
			}
			catch
			{
			}
		}

		private static void Check(Hand hand)
		{
			if ((Object)(object)hand == (Object)null)
			{
				return;
			}
			HandReciever farHoveringReciever = hand.farHoveringReciever;
			if ((Object)(object)farHoveringReciever == (Object)null)
			{
				return;
			}
			bool flag = false;
			try
			{
				BaseController controller = hand.Controller;
				flag = (Object)(object)controller != (Object)null && (controller.GetPrimaryInteractionButton() || controller.GetGrabbedState());
			}
			catch
			{
			}
			if (!flag)
			{
				return;
			}
			Magazine componentInParent = ((Component)farHoveringReciever).GetComponentInParent<Magazine>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return;
			}
			AmmoPlug magazinePlug = componentInParent.magazinePlug;
			if (!((Object)(object)magazinePlug == (Object)null))
			{
				if (Rails.IsRailed(magazinePlug))
				{
					Rails.RequestFree(magazinePlug);
				}
				int instanceID = ((Object)magazinePlug).GetInstanceID();
				if (_pulledAt.Count > 32)
				{
					Prune(_pulledAt, 1.5f);
				}
				_pulledAt[instanceID] = Time.unscaledTime;
			}
		}

		internal static void OnAttach(AmmoPlug plug)
		{
			try
			{
				int instanceID = ((Object)plug).GetInstanceID();
				if (!_pulledAt.TryGetValue(instanceID, out var value))
				{
					return;
				}
				_pulledAt.Remove(instanceID);
				float unscaledTime = Time.unscaledTime;
				if (!(unscaledTime - value > 1.5f))
				{
					if (_landedAt.Count > 32)
					{
						Prune(_landedAt, 0.35f);
					}
					_landedAt[instanceID] = unscaledTime;
					L.T("FORCE-PULL mag landed in hand; catch held off for a moment");
				}
			}
			catch
			{
			}
		}

		internal static bool JustLanded(int plugId, float now)
		{
			if (_landedAt.Count == 0)
			{
				return false;
			}
			if (!_landedAt.TryGetValue(plugId, out var value))
			{
				return false;
			}
			if (now - value < 0.35f)
			{
				return true;
			}
			_landedAt.Remove(plugId);
			return false;
		}

		internal static void Reset()
		{
			_pulledAt.Clear();
			_landedAt.Clear();
		}

		private static void Prune(Dictionary<int, float> d, float maxAge)
		{
			float unscaledTime = Time.unscaledTime;
			List<int> list = new List<int>();
			foreach (KeyValuePair<int, float> item in d)
			{
				if (unscaledTime - item.Value > maxAge)
				{
					list.Add(item.Key);
				}
			}
			for (int i = 0; i < list.Count; i++)
			{
				d.Remove(list[i]);
			}
		}
	}
	internal static class Geom
	{
		private const float MinLen = 0.01f;

		private const float MaxLen = 0.4f;

		private const float MeasureTolerance = 0.003f;

		private const float AxisAgreeDeg = 5f;

		private const float RootCheckInterval = 0.25f;

		internal static bool Ensure(Well w)
		{
			if (w.HasGeom && (Object)(object)w.GunRb != (Object)null && (Object)(object)w.Socket != (Object)null)
			{
				float unscaledTime = Time.unscaledTime;
				if (unscaledTime < w.NextRootCheck)
				{
					return true;
				}
				w.NextRootCheck = unscaledTime + 0.25f;
				int num = 0;
				try
				{
					num = ((Object)((Component)w.Socket).transform.root).GetInstanceID();
				}
				catch
				{
				}
				if (num == w.RootId)
				{
					return true;
				}
				if (w.Rail != null)
				{
					Rails.Release(w, "gun re-parented");
				}
				w.HasGeom = false;
			}
			float unscaledTime2 = Time.unscaledTime;
			if (unscaledTime2 < w.NextGeomTry)
			{
				return false;
			}
			w.NextGeomTry = unscaledTime2 + (w.RigRefused ? 0.15f : 0.5f);
			return Derive(w);
		}

		private static Rigidbody ResolveGunBody(Well w, AmmoSocket s)
		{
			Rigidbody val = null;
			try
			{
				Gun gun = s.gun;
				if ((Object)(object)gun != (Object)null)
				{
					try
					{
						InteractableHost host = gun.host;
						if ((Object)(object)host != (Object)null)
						{
							val = host.Rb;
						}
					}
					catch
					{
					}
					if ((Object)(object)val == (Object)null)
					{
						try
						{
							val = ((Component)gun).GetComponent<Rigidbody>();
						}
						catch
						{
						}
					}
					if ((Object)(object)val == (Object)null)
					{
						try
						{
							val = ((Component)gun).GetComponentInParent<Rigidbody>();
						}
						catch
						{
						}
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)s).GetComponentInParent<Rigidbody>();
				}
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			if (IsRigBody(val))
			{
				int num = 0;
				try
				{
					num = ((Object)((Component)s).transform.root).GetInstanceID();
				}
				catch
				{
				}
				if (w != null && w.RigRefusedRoot != num)
				{
					w.RigRefusedRoot = num;
					L.T("GEOM     '" + Names.Of((Component)(object)s) + "' gun body belongs to a rig, refusing to rail (holstered?)");
				}
				if (w != null)
				{
					w.RigRefused = true;
				}
				return null;
			}
			if (w != null)
			{
				w.RigRefusedRoot = 0;
				w.RigRefused = false;
			}
			return val;
		}

		internal static bool IsRigBody(Rigidbody rb)
		{
			try
			{
				return (Object)(object)rb == (Object)null || (Object)(object)((Component)rb).GetComponentInParent<RigManager>() != (Object)null;
			}
			catch
			{
				return true;
			}
		}

		private static bool Fail(Well w, string why)
		{
			w.HasGeom = false;
			w.GeomSource = "none";
			if (w.LastFailWhy != why)
			{
				w.LastFailWhy = why;
				L.T("GEOM     '" + Names.Of((Component)(object)w.Socket) + "' no rail: " + why);
			}
			return false;
		}

		private static float DefaultLen(Well w)
		{
			if (!Wells.IsPistol(w))
			{
				return 0.045f;
			}
			return 0.1f;
		}

		private static bool TakesSingleRounds(AmmoSocket s)
		{
			try
			{
				if (s.despawnOnInsert)
				{
					return true;
				}
			}
			catch
			{
			}
			try
			{
				Gun gun = s.gun;
				MagazineData val = (((Object)(object)gun == (Object)null) ? null : gun.defaultMagazine);
				if ((Object)(object)val != (Object)null && val.rounds >= 1 && val.rounds <= 2)
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		internal static float InwardSign(Magazine mag, AmmoPlug plug, Quaternion rot, Vector3 axisW)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0050: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)mag == (Object)null || (Object)(object)plug == (Object)null)
				{
					return 0f;
				}
				Transform transform = ((Component)mag).transform;
				Rigidbody component = ((Component)mag).GetComponent<Rigidbody>();
				Vector3 val = (((Object)(object)component != (Object)null) ? component.worldCenterOfMass : transform.position);
				Vector3 val2 = ((Component)plug).transform.position - val;
				val2 = rot * (Quaternion.Inverse(transform.rotation) * val2);
				float magnitude = ((Vector3)(ref val2)).magnitude;
				if (magnitude < 0.01f)
				{
					return 0f;
				}
				float num = Vector3.Dot(val2, axisW) / magnitude;
				if (num > 0.3f)
				{
					return 1f;
				}
				if (num < -0.3f)
				{
					return -1f;
				}
			}
			catch
			{
			}
			return 0f;
		}

		internal static void CheckSignWithMag(Well w, AmmoPlug plug)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (w.SignChecked || !w.HasGeom)
			{
				return;
			}
			try
			{
				Magazine magazine = plug.magazine;
				if (!((Object)(object)magazine == (Object)null) && SeatRotation(w, plug, out var rotW) && AlignWithMag(w, magazine, plug, rotW, "the first mag offered"))
				{
					w.SignChecked = true;
				}
			}
			catch
			{
			}
		}

		internal static bool AlignWithMag(Well w, Magazine mag, AmmoPlug plug, Quaternion seatRot, string from)
		{
			//IL_0020: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: 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_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: 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_02c0: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Transform transform = ((Component)mag).transform;
				Rigidbody component = ((Component)mag).GetComponent<Rigidbody>();
				Vector3 val = (((Object)(object)component != (Object)null) ? component.worldCenterOfMass : transform.position);
				Vector3 val2 = seatRot * (Quaternion.Inverse(transform.rotation) * (((Component)plug).transform.position - val));
				float magnitude = ((Vector3)(ref val2)).magnitude;
				if (magnitude < 0.01f)
				{
					return false;
				}
				val2 /= magnitude;
				Vector3 val3 = AxisW(w);
				float num = Vector3.Dot(val2, val3);
				if (num >= 0.5f)
				{
					return true;
				}
				if (num <= -0.5f)
				{
					w.AxisSL = -w.AxisSL;
					w.GeomSource += " flipped by the mag's shape";
					L.T($"GEOM     '{Names.Of((Component)(object)w.Socket)}' direction flipped: {from} says in is the other way");
					return true;
				}
				Vector3 val4 = ((Component)w.Socket).transform.InverseTransformDirection(val2);
				Vector3 normalized = ((Vector3)(ref val4)).normalized;
				Vector3 val5 = Vector3.right;
				float num2 = -2f;
				Vector3[] array = (Vector3[])(object)new Vector3[6]
				{
					Vector3.right,
					Vector3.left,
					Vector3.up,
					Vector3.down,
					Vector3.forward,
					Vector3.back
				};
				for (int i = 0; i < array.Length; i++)
				{
					float num3 = Vector3.Dot(array[i], normalized);
					if (num3 > num2)
					{
						num2 = num3;
						val5 = array[i];
					}
				}
				if (num2 < 0.7f)
				{
					return false;
				}
				w.AxisSL = val5;
				w.GeomSource += " axis from the mag's shape";
				L.T($"GEOM     '{Names.Of((Component)(object)w.Socket)}' socket +X is not the insertion axis ({Mathf.Acos(Mathf.Clamp(Mathf.Abs(num), 0f, 1f)) * 57.29578f:F0} deg off); using ({val5.x:F0},{val5.y:F0},{val5.z:F0}) from {from}");
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static bool Derive(Well w)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0574: Unknown result type (might be due to invalid IL or missing references)
			//IL_0579: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: 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_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_0465: Unknown result type (might be due to invalid IL or missing references)
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_04df: 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_04e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f9: 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_050a: Unknown result type (might be due to invalid IL or missing references)
			//IL_050e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0513: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_051a: Unknown result type (might be due to invalid IL or missing references)
			//IL_051f: 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_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_047a: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_048b: 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_049c: 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_04aa: 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_04b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0613: Unknown result type (might be due to invalid IL or missing references)
			//IL_0631: Unknown result type (might be due to invalid IL or missing references)
			//IL_064f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: 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_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0532: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Unknown result type (might be due to invalid IL or missing references)
			//IL_0538: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: 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_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0413: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0418: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: 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_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0427: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			AmmoSocket socket = w.Socket;
			if ((Object)(object)socket == (Object)null)
			{
				return Fail(w, "no socket");
			}
			Transform transform;
			Rigidbody val;
			try
			{
				transform = ((Component)socket).transform;
				val = ResolveGunBody(w, socket);
				if ((Object)(object)val == (Object)null)
				{
					return Fail(w, w.RigRefused ? "gun is on a body (holstered)" : "no gun body found");
				}
			}
			catch
			{
				return Fail(w, "could not read the gun");
			}
			w.GunRb = val;
			w.SingleRound = TakesSingleRounds(socket);
			w.GunPlatform = null;
			try
			{
				Gun gun = socket.gun;
				MagazineData val2 = (((Object)(object)gun == (Object)null) ? null : gun.defaultMagazine);
				if ((Object)(object)val2 != (Object)null)
				{
					w.GunPlatform = val2.platform;
				}
			}
			catch
			{
			}
			Vector3 val3 = Vector3.right;
			float num = 0f;
			string text = null;
			bool flag = false;
			bool flag2 = false;
			float num2 = 0f;
			try
			{
				num2 = ((Socket)socket).endDistance;
			}
			catch
			{
			}
			Vector3 val5;
			try
			{
				Transform endTransform = ((Socket)socket).endTransform;
				if ((Object)(object)endTransform != (Object)null)
				{
					Vector3 val4 = endTransform.position - transform.position;
					float magnitude = ((Vector3)(ref val4)).magnitude;
					if (magnitude >= 0.01f && magnitude <= 0.4f)
					{
						val5 = transform.InverseTransformDirection(val4 / magnitude);
						Vector3 normalized = ((Vector3)(ref val5)).normalized;
						float num3 = Vector3.Angle(normalized, val3);
						if (num3 > 5f && num3 < 175f)
						{
							val3 = normalized;
							text = "endTransform axis";
						}
						else
						{
							if (num3 >= 90f)
							{
								val3 = -val3;
							}
							text = "socket +X";
						}
						Vector3 val6 = val4;
						val5 = transform.TransformDirection(val3);
						num = Mathf.Abs(Vector3.Dot(val6, ((Vector3)(ref val5)).normalized));
						flag = true;
					}
					else if (magnitude < 0.01f)
					{
						flag2 = true;
					}
				}
			}
			catch
			{
			}
			if (text == null)
			{
				if (flag2 || num2 < 0.01f)
				{
					flag2 = true;
					num = ((num2 >= 0.02f && num2 <= 0.2f) ? num2 : DefaultLen(w));
					text = "seat at socket";
				}
				else
				{
					if (num2 > 0.4f)
					{
						return Fail(w, $"endDistance {num2:F3} is not a rail");
					}
					num = num2;
					text = "endDistance";
				}
			}
			bool geomChecked = false;
			try
			{
				Plug lockedPlug = ((Socket)socket).LockedPlug;
				if ((Object)(object)lockedPlug != (Object)null)
				{
					val5 = transform.TransformDirection(val3);
					Vector3 normalized2 = ((Vector3)(ref val5)).normalized;
					float num4 = Vector3.Dot(((Component)lockedPlug).transform.position - transform.position, normalized2);
					AmmoPlug val7 = null;
					Magazine val8 = null;
					try
					{
						val7 = ((Il2CppObjectBase)lockedPlug).TryCast<AmmoPlug>();
						val8 = (((Object)(object)val7 == (Object)null) ? null : val7.magazine);
					}
					catch
					{
					}
					bool flag3 = (Object)(object)val8 != (Object)null && val8.isMagazineInserted;
					if (Mathf.Abs(num4) < 0.01f)
					{
						if (!flag2)
						{
							flag2 = true;
							if (num < 0.02f || num > 0.2f)
							{
								num = DefaultLen(w);
							}
							text = "seat at socket (seen)";
						}
						float num5 = InwardSign(val8, val7, ((Object)(object)val8 != (Object)null) ? ((Component)val8).transform.rotation : Quaternion.identity, normalized2);
						if (num5 < 0f)
						{
							val3 = -val3;
							text += " flipped";
						}
						if (num5 != 0f)
						{
							flag = true;
						}
						if (flag3)
						{
							geomChecked = num5 != 0f;
						}
					}
					else if (!flag2)
					{
						if (num4 < 0f)
						{
							val3 = -val3;
							num4 = 0f - num4;
							text += " flipped";
						}
						flag = true;
						if (flag3)
						{
							if (num4 >= 0.01f && num4 <= 0.4f && Mathf.Abs(num4 - num) > 0.003f)
							{
								num = num4;
								text += " measured";
							}
							geomChecked = true;
						}
						else
						{
							text += " (mid-insert, length not measured)";
						}
					}
					else
					{
						float num6 = InwardSign(val8, val7, ((Object)(object)val8 != (Object)null) ? ((Component)val8).transform.rotation : Quaternion.identity, normalized2);
						if (num6 < 0f)
						{
							val3 = -val3;
							text += " flipped";
						}
						if (num6 != 0f)
						{
							flag = true;
						}
					}
				}
			}
			catch
			{
			}
			if (!flag)
			{
				try
				{
					val5 = transform.TransformDirection(val3);
					Vector3 normalized3 = ((Vector3)(ref val5)).normalized;
					Vector3 worldCenterOfMass = val.worldCenterOfMass;
					if (!flag2)
					{
						val5 = transform.position + normalized3 * num - worldCenterOfMass;
						float magnitude2 = ((Vector3)(ref val5)).magnitude;
						val5 = transform.position - normalized3 * num - worldCenterOfMass;
						if (((Vector3)(ref val5)).magnitude < magnitude2 * 0.8f)
						{
							val3 = -val3;
							text += " com-flipped";
						}
					}
					else
					{
						val5 = transform.position - normalized3 * num - worldCenterOfMass;
						float magnitude3 = ((Vector3)(ref val5)).magnitude;
						val5 = transform.position + normalized3 * num - worldCenterOfMass;
						if (((Vector3)(ref val5)).magnitude > magnitude3 * 1.25f)
						{
							val3 = -val3;
							text += " com-flipped";
						}
					}
				}
				catch
				{
				}
			}
			try
			{
				w.RootId = ((Object)transform.root).GetInstanceID();
			}
			catch
			{
				w.RootId = 0;
			}
			w.GunRb = val;
			w.AxisSL = ((Vector3)(ref val3)).normalized;
			w.RailLen = num;
			w.SeatAtSocket = flag2;
			w.MouthOffset = (flag2 ? (0f - num) : 0f);
			w.SignChecked = flag;
			w.GeomSource = text;
			w.GeomChecked = geomChecked;
			w.HasGeom = true;
			w.LastFailWhy = null;
			L.T($"GEOM     '{Names.Of((Component)(object)socket)}' len={num:F4} axisSL=({val3.x:F3},{val3.y:F3},{val3.z:F3}) src={text}" + (flag2 ? " [seats at the socket]" : "") + (w.SingleRound ? " [single rounds: tight native catch]" : ""));
			return true;
		}

		internal static void VerifyWithSeated(Well w, AmmoPlug plug)
		{
			//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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0047: 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_0049: 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_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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Ensure(w) || (Object)(object)plug == (Object)null || (Object)(object)w.Socket == (Object)null)
				{
					return;
				}
				Vector3 val = AxisW(w);
				Vector3 position = ((Component)w.Socket).transform.position;
				Vector3 position2 = ((Component)plug).transform.position;
				float num = Vector3.Dot(position2 - position, val);
				if (Mathf.Abs(num) < 0.01f)
				{
					if (!w.SeatAtSocket)
					{
						w.SeatAtSocket = true;
						if (w.RailLen < 0.02f || w.RailLen > 0.2f)
						{
							w.RailLen = DefaultLen(w);
						}
						w.GeomSource += " -> seats at the socket";
						L.T("GEOM     '" + Names.Of((Component)(object)w.Socket) + "' seats at the socket: rail rebuilt outward from it");
					}
					Magazine magazine = plug.magazine;
					if ((Object)(object)magazine != (Object)null && AlignWithMag(w, magazine, plug, ((Component)magazine).transform.rotation, "a real seat"))
					{
						w.SignChecked = true;
					}
					val = AxisW(w);
					num = Vector3.Dot(position2 - position, val);
					w.MouthOffset = num - w.RailLen;
					w.GeomChecked = true;
					return;
				}
				if (w.SeatAtSocket)
				{
					w.SeatAtSocket = false;
					w.MouthOffset = 0f;
					w.GeomSource += " -> seats away from the socket";
				}
				float num2 = num - w.MouthOffset;
				if (num2 < 0f && 0f - num2 >= 0.01f && 0f - num2 <= 0.4f)
				{
					w.AxisSL = -w.AxisSL;
					num2 = 0f - num2;
					w.GeomSource += " flipped";
					L.T("GEOM     '" + Names.Of((Component)(object)w.Socket) + "' axis flipped from a real seat");
				}
				if (num2 >= 0.01f && num2 <= 0.4f && Mathf.Abs(num2 - w.RailLen) > 0.003f)
				{
					L.T($"GEOM     '{Names.Of((Component)(object)w.Socket)}' travel {w.RailLen:F4} -> {num2:F4} from a real seat");
					w.RailLen = num2;
					w.GeomSource += " measured";
				}
				w.SignChecked = true;
				w.GeomChecked = true;
			}
			catch
			{
			}
		}

		internal static Vector3 BaseW(Well w)
		{
			//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_003b: 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_0036: 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_001e: 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_002b: 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_0035: 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)
			try
			{
				Vector3 val = ((Component)w.Socket).transform.position;
				if (w.MouthOffset != 0f)
				{
					val += AxisW(w) * w.MouthOffset;
				}
				return val;
			}
			catch
			{
				return Vector3.zero;
			}
		}

		internal static Vector3 AxisW(Well w)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//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_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_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_002a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 result;
			try
			{
				result = ((Component)w.Socket).transform.TransformDirection(w.AxisSL);
				result = ((Vector3)(ref result)).normalized;
			}
			catch
			{
				result = Vector3.up;
			}
			return result;
		}

		internal static Vector3 RailPoint(Well w, float t)
		{
			//IL_0001: 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_000d: 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)
			return BaseW(w) + AxisW(w) * t;
		}

		internal static void Where(Well w, Vector3 plugW, out float axial, out float lateral)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_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_002c: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = AxisW(w);
			Vector3 val2 = plugW - BaseW(w);
			axial = Vector3.Dot(val2, val);
			Vector3 val3 = val2 - val * axial;
			lateral = ((Vector3)(ref val3)).magnitude;
		}

		internal static float Axial(Well w, Vector3 plugW)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.Dot(plugW - BaseW(w), AxisW(w));
		}

		internal static bool PoseAt(Well w, AmmoPlug plug, float t, out Vector3 magPosW, out Quaternion magRotW)
		{
			//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_000d: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			magPosW = Vector3.zero;
			magRotW = Quaternion.identity;
			try
			{
				Magazine magazine = plug.magazine;
				if ((Object)(object)magazine == (Object)null || (Object)(object)w.Socket == (Object)null || (Object)(object)w.GunRb == (Object)null)
				{
					return false;
				}
				Transform transform = ((Component)w.Socket).transform;
				Transform transform2 = ((Component)magazine).transform;
				Transform transform3 = ((Component)plug).transform;
				Quaternion val = Quaternion.Inverse(transform2.rotation) * transform3.rotation;
				magRotW = transform.rotation * Quaternion.Inverse(val);
				Quaternion val2 = magRotW * Quaternion.Inverse(transform2.rotation);
				magPosW = RailPoint(w, t) + val2 * (transform2.position - transform3.position);
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static bool SeatRotation(Well w, AmmoPlug plug, out Quaternion rotW)
		{
			Vector3 magPosW;
			return PoseAt(w, plug, w.RailLen, out magPosW, out rotW);
		}
	}
	internal enum BuzzKind
	{
		Catch,
		Slide,
		Insert
	}
	internal static class Grips
	{
		private sealed class SavedVc
		{
			public VirtualControllerSettings S;

			public IntPtr Ptr;

			public float Look;

			public float Twist;

			public float Swing;

			public float Pos;

			public float SwingLim;

			public float TwistLim;
		}

		private sealed class HandLock
		{
			public IntPtr Hand;

			public Well W;

			public ConfigurableJoint Joint;

			public IntPtr JointPtr;

			public float JointSeenAt;

			public bool JointLocked;

			public ConfigurableJointMotion AX;

			public ConfigurableJointMotion AY;

			public ConfigurableJointMotion AZ;

			public readonly List<SavedVc> Saved = new List<SavedVc>(3);

			public int Role = -1;

			public bool Logged;
		}

		internal static readonly List<AmmoPlug> Held = new List<AmmoPlug>();

		internal static bool HooksOk;

		internal static bool HooksProven;

		private static float _sweepAccum;

		private const float SweepInterval = 1.5f;

		private const float HoldBreakForce = 6000f;

		private const float HoldBreakTorque = 600f;

		private static readonly List<HandLock> _locks = new List<HandLock>(2);

		private const float LockAfter = 0.1f;

		private static bool _loggedHandBodies;

		private static readonly Dictionary<IntPtr, Rigidbody> _offByUs = new Dictionary<IntPtr, Rigidbody>();

		private static float _healAccum;

		private static readonly Dictionary<IntPtr, Rigidbody> _kept = new Dictionary<IntPtr, Rigidbody>();

		private static readonly List<Collider> _liveA = new List<Collider>(32);

		private static readonly List<Collider> _liveB = new List<Collider>(64);

		internal static int LockedCount => _locks.Count;

		internal static void OnAttach(InteractableHost host, Hand hand)
		{
			try
			{
				if ((Object)(object)host == (Object)null || !IsLocalHand(hand))
				{
					return;
				}
				Magazine componentInParent = ((Component)host).GetComponentInParent<Magazine>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					return;
				}
				AmmoPlug magazinePlug = componentInParent.magazinePlug;
				if (!((Object)(object)magazinePlug == (Object)null))
				{
					Add(magazinePlug);
					ForcePulls.OnAttach(magazinePlug);
					Wells.WantSweep = true;
					if (!HooksProven)
					{
						HooksProven = true;
						L.T("grab hook confirmed live; held-mag scanning off");
					}
					if (componentInParent.isMagazineInserted)
					{
						Wells.NoteGrabOnSeated(magazinePlug, hand);
					}
				}
			}
			catch
			{
			}
		}

		internal static void OnDetach(InteractableHost host, Hand hand)
		{
			try
			{
				if ((Object)(object)host == (Object)null)
				{
					return;
				}
				Magazine componentInParent = ((Component)host).GetComponentInParent<Magazine>();
				if (!((Object)(object)componentInParent == (Object)null))
				{
					AmmoPlug magazinePlug = componentInParent.magazinePlug;
					if (!((Object)(object)magazinePlug == (Object)null) && !IsHeld(magazinePlug))
					{
						Remove(magazinePlug);
					}
				}
			}
			catch
			{
			}
		}

		private static void Add(AmmoPlug plug)
		{
			for (int i = 0; i < Held.Count; i++)
			{
				if ((Object)(object)Held[i] != (Object)null && ((Il2CppObjectBase)Held[i]).Pointer == ((Il2CppObjectBase)plug).Pointer)
				{
					return;
				}
			}
			Held.Add(plug);
		}

		private static void Remove(AmmoPlug plug)
		{
			for (int num = Held.Count - 1; num >= 0; num--)
			{
				AmmoPlug val = Held[num];
				if ((Object)(object)val == (Object)null || ((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)plug).Pointer)
				{
					Held.RemoveAt(num);
				}
			}
		}

		internal static void Clear()
		{
			Held.Clear();
		}

		internal static void Tidy()
		{
			for (int num = Held.Count - 1; num >= 0; num--)
			{
				AmmoPlug val = Held[num];
				bool flag = false;
				try
				{
					Magazine val2 = (((Object)(object)val == (Object)null) ? null : val.magazine);
					flag = (Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeInHierarchy && IsHeld(val);
				}
				catch
				{
				}
				if (!flag)
				{
					Held.RemoveAt(num);
				}
			}
		}

		internal static void MaybeSweep(float dt, bool force)
		{
			//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)
			if (HooksOk && HooksProven && !force)
			{
				_sweepAccum = 0f;
				return;
			}
			_sweepAccum += dt;
			if (!force && _sweepAccum < 1.5f)
			{
				return;
			}
			_sweepAccum = 0f;
			try
			{
				Il2CppArrayBase<AmmoPlug> val = Resources.FindObjectsOfTypeAll<AmmoPlug>();
				if (val == null)
				{
					return;
				}
				for (int i = 0; i < val.Length; i++)
				{
					AmmoPlug val2 = val[i];
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					try
					{
						Scene scene = ((Component)val2).gameObject.scene;
						if (((Scene)(ref scene)).IsValid() && !((Object)(object)val2.magazine == (Object)null) && IsHeld(val2))
						{
							Add(val2);
						}
					}
					catch
					{
					}
				}
			}
			catch
			{
			}
		}

		internal static bool IsHeld(AmmoPlug plug)
		{
			try
			{
				InteractableHost host = ((Plug)plug).host;
				return (Object)(object)host != (Object)null && (Object)(object)host.GetHand(0) != (Object)null;
			}
			catch
			{
				return false;
			}
		}

		internal static Hand HandOf(AmmoPlug plug)
		{
			try
			{
				InteractableHost host = ((Plug)plug).host;
				return ((Object)(object)host == (Object)null) ? null : host.GetHand(0);
			}
			catch
			{
				return null;
			}
		}

		internal static bool IsLocalHand(Hand hand)
		{
			try
			{
				if ((Object)(object)hand == (Object)null)
				{
					return false;
				}
				Hand val = null;
				Hand val2 = null;
				try
				{
					val = Player.LeftHand;
				}
				catch
				{
				}
				try
				{
					val2 = Player.RightHand;
				}
				catch
				{
				}
				if ((Object)(object)val != (Object)null || (Object)(object)val2 != (Object)null)
				{
					return ((Object)(object)val != (Object)null && ((Il2CppObjectBase)hand).Pointer == ((Il2CppObjectBase)val).Pointer) || ((Object)(object)val2 != (Object)null && ((Il2CppObjectBase)hand).Pointer == ((Il2CppObjectBase)val2).Pointer);
				}
				RigManager rigManager = Player.RigManager;
				RigManager manager = hand.manager;
				if ((Object)(object)rigManager == (Object)null || (Object)(object)manager == (Object)null)
				{
					return true;
				}
				return ((Il2CppObjectBase)manager).Pointer == ((Il2CppObjectBase)rigManager).Pointer;
			}
			catch
			{
				return true;
			}
		}

		internal static bool HeldLocally(AmmoPlug plug)
		{
			Hand val = HandOf(plug);
			if ((Object)(object)val != (Object)null)
			{
				return IsLocalHand(val);
			}
			return false;
		}

		internal static Hand LocalHandByPtr(IntPtr p)
		{
			if (p == IntPtr.Zero)
			{
				return null;
			}
			try
			{
				Hand leftHand = Player.LeftHand;
				if ((Object)(object)leftHand != (Object)null && ((Il2CppObjectBase)leftHand).Pointer == p)
				{
					return leftHand;
				}
			}
			catch
			{
			}
			try
			{
				Hand rightHand = Player.RightHand;
				if ((Object)(object)rightHand != (Object)null && ((Il2CppObjectBase)rightHand).Pointer == p)
				{
					return rightHand;
				}
			}
			catch
			{
			}
			return null;
		}

		internal static bool HostHeldBy(InteractableHost host, IntPtr hand)
		{
			if ((Object)(object)host == (Object)null || hand == IntPtr.Zero)
			{
				return false;
			}
			for (int i = 0; i < 2; i++)
			{
				try
				{
					Hand hand2 = host.GetHand(i);
					if ((Object)(object)hand2 != (Object)null && ((Il2CppObjectBase)hand2).Pointer == hand)
					{
						return true;
					}
				}
				catch
				{
				}
			}
			return false;
		}

		internal static float GripForce(Hand hand)
		{
			try
			{
				BaseController val = (((Object)(object)hand == (Object)null) ? null : hand.Controller);
				return ((Object)(object)val == (Object)null) ? (-1f) : val.GetGripForce();
			}
			catch
			{
				return -1f;
			}
		}

		internal static bool HandEmpty(Hand hand)
		{
			try
			{
				return (Object)(object)hand != (Object)null && (Object)(object)hand.m_CurrentAttachedGO == (Object)null;
			}
			catch
			{
				return true;
			}
		}

		internal static string AttachedName(Hand hand)
		{
			try
			{
				GameObject val = (((Object)(object)hand == (Object)null) ? null : hand.m_CurrentAttachedGO);
				return ((Object)(object)val == (Object)null) ? null : ((Object)val).name;
			}
			catch
			{
				return null;
			}
		}

		internal static bool HoldsGunPart(Hand hand, Rigidbody gunRb, Magazine seated)
		{
			try
			{
				GameObject val = (((Object)(object)hand == (Object)null) ? null : hand.m_CurrentAttachedGO);
				if ((Object)(object)val == (Object)null || (Object)(object)gunRb == (Object)null)
				{
					return false;
				}
				Transform transform = val.transform;
				if (!transform.IsChildOf(((Component)gunRb).transform))
				{
					return false;
				}
				return (Object)(object)seated == (Object)null || !transform.IsChildOf(((Component)seated).transform);
			}
			catch
			{
				return false;
			}
		}

		internal static Transform ControllerOf(Hand hand)
		{
			try
			{
				BaseController val = (((Object)(object)hand == (Object)null) ? null : hand.Controller);
				return ((Object)(object)val == (Object)null) ? null : ((Component)val).transform;
			}
			catch
			{
				return null;
			}
		}

		internal static ConfigurableJoint MakeHold(Rigidbody handRb, Rigidbody gunRb)
		{
			if ((Object)(object)handRb == (Object)null || (Object)(object)gunRb == (Object)null)
			{
				return null;
			}
			ConfigurableJoint val = null;
			try
			{
				val = ((Component)handRb).gameObject.AddComponent<ConfigurableJoint>();
				((Joint)val).connectedBody = gunRb;
				val.xMotion = (ConfigurableJointMotion)0;
				val.yMotion = (ConfigurableJointMotion)0;
				val.zMotion = (ConfigurableJointMotion)0;
				val.angularXMotion = (ConfigurableJointMotion)0;
				val.angularYMotion = (ConfigurableJointMotion)0;
				val.angularZMotion = (ConfigurableJointMotion)0;
				((Joint)val).enableCollision = false;
				((Joint)val).enablePreprocessing = false;
				((Joint)val).breakForce = 6000f;
				((Joint)val).breakTorque = 600f;
				((Joint)val).autoConfigureConnectedAnchor = false;
				return val;
			}
			catch
			{
				try
				{
					if ((Object)(object)val != (Object)null)
					{
						Object.Destroy((Object)(object)val);
					}
				}
				catch
				{
				}
				return null;
			}
		}

		internal static void DestroyHold(ConfigurableJoint j)
		{
			try
			{
				if (!((Object)(object)j == (Object)null))
				{
					if (Rails.InTick)
					{
						Object.DestroyImmediate((Object)(object)j);
					}
					else
					{
						Object.Destroy((Object)(object)j);
					}
				}
			}
			catch
			{
			}
		}

		internal static bool ForceGrab(Magazine mag, InteractableHost host, Hand hand)
		{
			if ((Object)(object)mag == (Object)null || (Object)(object)host == (Object)null || (Object)(object)hand == (Object)null)
			{
				return false;
			}
			if (!HandEmpty(hand))
			{
				return false;
			}
			try
			{
				if (mag.isMagazineInserted)
				{
					return false;
				}
			}
			catch
			{
				return false;
			}
			bool flag = false;
			try
			{
				if (host.IsInteractionDisabled)
				{
					host.EnableInteraction();
					flag = true;
				}
				Grip grip = mag.grip;
				if ((Object)(object)grip != (Object)null)
				{
					try
					{
						grip.OnHandHoverBegin(hand, true);
					}
					catch
					{
					}
					try
					{
						grip.OnGrabConfirm(hand, true);
					}
					catch
					{
					}
					EndHoverBlend(hand);
				}
			}
			catch
			{
			}
			bool flag2 = HostHeldBy(host, ((Il2CppObjectBase)hand).Pointer);
			if (!flag2 && flag)
			{
				try
				{
					host.DisableInteraction();
				}
				catch
				{
				}
			}
			return flag2;
		}

		internal static void EndHoverBlend(Hand hand)
		{
			try
			{
				SkeletonHand val = (((Object)(object)hand == (Object)null) ? null : hand.Skeleton);
				if ((Object)(object)val != (Object)null)
				{
					val.OnGripHoverEnd();
				}
			}
			catch
			{
			}
		}

		internal static bool HandOnGrip(Hand hand, Grip grip)
		{
			try
			{
				if ((Object)(object)hand == (Object)null || (Object)(object)grip == (Object)null)
				{
					return false;
				}
				GameObject currentAttachedGO = hand.m_CurrentAttachedGO;
				return (Object)(object)currentAttachedGO != (Object)null && ((Il2CppObjectBase)currentAttachedGO).Pointer == ((Il2CppObjectBase)((Component)grip).gameObject).Pointer;
			}
			catch
			{
				return false;
			}
		}

		internal static bool ProxyJointOk(Hand hand, Rigidbody gunRb)
		{
			//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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			try
			{
				ConfigurableJoint joint = hand.joint;
				if ((Object)(object)joint == (Object)null || (Object)(object)hand.tempJoint != (Object)null || (Object)(object)gunRb == (Object)null)
				{
					return false;
				}
				Rigidbody connectedBody = ((Joint)joint).connectedBody;
				return (Object)(object)connectedBody != (Object)null && ((Il2CppObjectBase)connectedBody).Pointer == ((Il2CppObjectBase)gunRb).Pointer && (int)joint.xMotion == 0 && (int)joint.yMotion == 0 && (int)joint.zMotion == 0;
			}
			catch
			{
				return false;
			}
		}

		internal static bool OtherHandOn(Grip grip, IntPtr ours)
		{
			try
			{
				List<Hand> attachedHands = grip.attachedHands;
				if (attachedHands == null)
				{
					return false;
				}
				for (int i = 0; i < attachedHands.Count; i++)
				{
					Hand val = attachedHands[i];
					if ((Object)(object)val != (Object)null && ((Il2CppObjectBase)val).Pointer != ours)
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		internal static Grip ProxyFor(Well w, AmmoPlug plug, Magazine mag, Hand hand, out string why, float maxDist = 0.15f)
		{
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			why = null;
			try
			{
				if (!Hooks.ProxyHooksOk)
				{
					why = "proxy hooks not installed";
					return null;
				}
				if (Hooks.ProxySuppressBroken)
				{
					why = "the pull-out suppression failed earlier";
					return null;
				}
				AmmoSocket socket = w.Socket;
				Gun gun = socket.gun;
				if ((Object)(object)gun == (Object)null)
				{
					why = "no Gun on the socket";
					return null;
				}
				Grip proxyGrip = ((Socket)socket).proxyGrip;
				if ((Object)(object)proxyGrip == (Object)null)
				{
					why = "the gun has no mag grip";
					return null;
				}
				string text = "?";
				try
				{
					text = ((Object)proxyGrip).GetIl2CppType().FullName;
				}
				catch
				{
				}
				if (text != "SLZ.Marrow.TargetGrip" && text != "Il2CppSLZ.Marrow.TargetGrip")
				{
					why = "the gun's mag grip is a " + text;
					return null;
				}
				if (!((Behaviour)proxyGrip).enabled || !((Component)proxyGrip).gameObject.activeInHierarchy)
				{
					why = "the gun's mag grip is inactive";
					return null;
				}
				InteractableHost host = ((Socket)socket).host;
				if ((Object)(object)host == (Object)null || (Object)(object)gun.host == (Object)null || ((Il2CppObjectBase)host).Pointer != ((Il2CppObjectBase)gun.host).Pointer)
				{
					why = "the socket's host is not the gun's";
					return null;
				}
				IGrippable host2 = ((HandReciever)proxyGrip).Host;
				if (host2 == null || ((Il2CppObjectBase)host2).Pointer != ((Il2CppObjectBase)host).Pointer)
				{
					why = "the mag grip is not hosted by the gun";
					return null;
				}
				if (host.IsStatic)
				{
					why = "the gun is static";
					return null;
				}
				Rigidbody rb = host.Rb;
				if ((Object)(object)rb == (Object)null || (Object)(object)w.GunRb == (Object)null || ((Il2CppObjectBase)rb).Pointer != ((Il2CppObjectBase)w.GunRb).Pointer)
				{
					why = "the gun's host body is not the rail's";
					return null;
				}
				if (rb.isKinematic)
				{
					why = "the gun's body is kinematic";
					return null;
				}
				HandJointConfiguration handJointConfig = ((HandReciever)proxyGrip).HandJointConfig;
				if (handJointConfig == null || (int)handJointConfig.xMotion != 0)
				{
					why = "the mag grip's joint is not locked";
					return null;
				}
				if ((Object)(object)proxyGrip.GetHand() != (Object)null)
				{
					why = "a hand already holds the mag grip";
					return null;
				}
				if (gun.isMagEjectOnEmpty)
				{
					why = "the gun ejects on empty";
					return null;
				}
				if (!((AlignPlug)plug)._isLocked || ((AlignPlug)plug)._isExitTransition || ((AlignPlug)plug)._isEnterTransition)
				{
					why = "the mag is not settled in the well";
					return null;
				}
				Grip grip = mag.grip;
				Transform val = (((Object)(object)grip == (Object)null) ? null : grip.targetTransform);
				if ((Object)(object)val == (Object)null)
				{
					why = "the mag's grip has no target";
					return null;
				}
				if ((Object)(object)hand.Skeleton == (Object)null || (Object)(object)hand.Animator == (Object)null || (Object)(object)hand.Controller == (Object)null || (Object)(object)hand.physHand == (Object)null || (Object)(object)hand.slot == (Object)null)
				{
					why = "the hand is not fully set up";
					return null;
				}
				Rigidbody val2 = BodyOf(hand);
				float num = (((Object)(object)val2 == (Object)null) ? 99f : Vector3.Distance(val2.position, val.position));
				if (num > maxDist)
				{
					why = $"the hand is {num * 100f:F0} cm from the mag";
					return null;
				}
				return proxyGrip;
			}
			catch (Exception ex)
			{
				why = "check failed: " + ex.Message;
				return null;
			}
		}

		internal static int DropDoomedMagJoints(Hand hand, Magazine mag)
		{
			int num = 0;
			try
			{
				Rigidbody val = BodyOf(hand);
				if ((Object)(object)val == (Object)null || (Object)(object)mag == (Object)null)
				{
					return 0;
				}
				Il2CppArrayBase<ConfigurableJoint> components = ((Component)val).GetComponents<ConfigurableJoint>();
				if (components == null)
				{
					return 0;
				}
				IntPtr pointer = ((Il2CppObjectBase)((Component)mag).gameObject).Pointer;
				IntPtr intPtr = IntPtr.Zero;
				IntPtr intPtr2 = IntPtr.Zero;
				try
				{
					ConfigurableJoint joint = hand.joint;
					if ((Object)(object)joint != (Object)null)
					{
						intPtr = ((Il2CppObjectBase)joint).Pointer;
					}
				}
				catch
				{
				}
				try
				{
					ConfigurableJoint tempJoint = hand.tempJoint;
					if ((Object)(object)tempJoint != (Object)null)
					{
						intPtr2 = ((Il2CppObjectBase)tempJoint).Pointer;
					}
				}
				catch
				{
				}
				for (int i = 0; i < components.Length; i++)
				{
					ConfigurableJoint val2 = components[i];
					if (!((Object)(object)val2 == (Object)null) && !(((Il2CppObjectBase)val2).Pointer == intPtr) && !(((Il2CppObjectBase)val2).Pointer == intPtr2))
					{
						Rigidbody val3 = null;
						try
						{
							val3 = ((Joint)val2).connectedBody;
						}
						catch
						{
						}
						if (!((Object)(object)val3 == (Object)null) && !(((Il2CppObjectBase)((Component)val3).gameObject).Pointer != pointer))
						{
							DestroyHold(val2);
							num++;
						}
					}
				}
			}
			catch
			{
			}
			return num;
		}

		internal static bool ProxyGrab(Hand hand, Grip proxy, Magazine mag, AmmoPlug plug, Rigidbody gunRb, out string report)
		{
			//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_00c7: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			Vector3 position;
			Quaternion rotation;
			try
			{
				Transform targetTransform = mag.grip.targetTransform;
				position = targetTransform.position;
				rotation = targetTransform.rotation;
			}
			catch
			{
				report = " (no mag target)";
				return false;
			}
			int num = DropDoomedMagJoints(hand, mag);
			StringBuilder stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler;
			if (num > 0)
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder3 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(20, 1, stringBuilder2);
				handler.AppendLiteral(" old-joints-dropped=");
				handler.AppendFormatted(num);
				stringBuilder3.Append(ref handler);
			}
			try
			{
				HandToGripState handState = proxy.GetHandState(hand);
				List<Coroutine> val = ((handState == null) ? null : handState.coroutines);
				if (val != null && val.Count > 0)
				{
					val.Clear();
					stringBuilder.Append(" stale-snatch-cleared");
				}
			}
			catch
			{
			}
			int proxyGrabsSuppressed = Hooks.ProxyGrabsSuppressed;
			try
			{
				EndHoverBlend(hand);
				hand.HoveringReceiver = (HandReciever)(object)proxy;
				hand.farHoveringReciever = null;
				proxy.SetTargetInWorld(hand, position, rotation);
				proxy.OnGrabConfirm(hand, true);
			}
			catch (Exception ex)
			{
				stringBuilder.Append(" grab-threw: " + ex.Message);
			}
			bool flag = HandOnGrip(hand, proxy);
			bool flag2 = flag && ProxyJointOk(hand, gunRb);
			float num2 = -1f;
			try
			{
				num2 = Vector3.Distance(proxy.GetTargetInWorld(hand).position, position);
			}
			catch
			{
			}
			float num3 = -1f;
			try
			{
				ConfigurableJoint joint = hand.joint;
				if ((Object)(object)joint != (Object)null && (Object)(object)gunRb != (Object)null)
				{
					num3 = Vector3.Distance(((Component)joint).transform.TransformPoint(((Joint)joint).anchor), ((Component)gunRb).transform.TransformPoint(((Joint)joint).connectedAnchor));
				}
			}
			catch
			{
			}
			bool value = Hooks.ProxyGrabsSuppressed > proxyGrabsSuppressed;
			bool flag3 = false;
			try
			{
				flag3 = ((AlignPlug)plug)._isExitTransition;
			}
			catch
			{
			}
			if (flag3)
			{
				try
				{
					((AlignPlug)plug)._isExitTransition = false;
				}
				catch
				{
				}
				Hooks.ProxySuppressBroken = true;
				L.W("keep hand: the game's mag pull-out was not suppressed; stopped it by hand. Later keeps hold without the grip pose.");
			}
			bool flag4 = flag && flag2 && num2 >= 0f && num2 < 0.005f;
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(87, 7, stringBuilder2);
			handler.AppendLiteral(" | attached=");
			handler.AppendFormatted(flag);
			handler.AppendLiteral(" joint=");
			handler.AppendFormatted(((Object)(object)hand.joint == (Object)null) ? "none" : JointInfo(hand.joint));
			handler.AppendLiteral(" ");
			handler.AppendLiteral("on-gun=");
			handler.AppendFormatted(flag2);
			handler.AppendLiteral(" target-err=");
			handler.AppendFormatted(num2 * 1000f, "F1");
			handler.AppendLiteral("mm gap=");
			handler.AppendFormatted(num3 * 1000f, "F0");
			handler.AppendLiteral("mm ");
			handler.AppendLiteral("pull-out-suppressed=");
			handler.AppendFormatted(value);
			handler.AppendLiteral(" pull-out-started=");
			handler.AppendFormatted(flag3);
			stringBuilder4.Append(ref handler);
			if (!flag4)
			{
				if (HandOnGrip(hand, proxy))
				{
					try
					{
						proxy.ForceDetach(hand);
					}
					catch
					{
					}
				}
				else
				{
					try
					{
						HandReciever hoveringReceiver = hand.HoveringReceiver;
						if ((Object)(object)hoveringReceiver != (Object)null && ((Il2CppObjectBase)hoveringReceiver).Pointer == ((Il2CppObjectBase)proxy).Pointer)
						{
							hand.HoveringReceiver = null;
						}
					}
					catch
					{
					}
				}
				try
				{
					if ((Object)(object)hand.tempJoint != (Object)null)
					{
						hand.DetachJoint(true, (Grip)null);
					}
				}
				catch
				{
				}
				EndHoverBlend(hand);
				try
				{
					Rigidbody lowerArmRb = hand.physHand._lowerArmRb;
					if ((Object)(object)lowerArmRb != (Object)null && !lowerArmRb.detectCollisions)
					{
						lowerArmRb.detectCollisions = true;
					}
				}
				catch
				{
				}
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder5 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(31, 1, stringBuilder2);
				handler.AppendLiteral(" -> taken back off, hand empty=");
				handler.AppendFormatted(HandEmpty(hand));
				stringBuilder5.Append(ref handler);
			}
			report = stringBuilder.ToString();
			return flag4;
		}

		internal static void RideProxyTarget(Hand hand, Grip proxy, Magazine mag, Rigidbody gunRb)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			try
			{
				if ((Object)(object)hand == (Object)null || (Object)(object)proxy == (Object)null || (Object)(object)mag == (Object)null || (Object)(object)gunRb == (Object)null)
				{
					return;
				}
				Grip grip = mag.grip;
				Transform val = (((Object)(object)grip == (Object)null) ? null : grip.targetTransform);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Vector3 position = val.position;
				proxy.SetTargetInWorld(hand, position, val.rotation);
				ConfigurableJoint joint = hand.joint;
				if (!((Object)(object)joint == (Object)null))
				{
					Rigidbody connectedBody = ((Joint)joint).connectedBody;
					if (!((Object)(object)connectedBody == (Object)null) && !(((Il2CppObjectBase)connectedBody).Pointer != ((Il2CppObjectBase)gunRb).Pointer))
					{
						((Joint)joint).connectedAnchor = ((Component)gunRb).transform.InverseTransformPoint(position);
					}
				}
			}
			catch
			{
			}
		}

		internal static bool VanillaGrab(Hand hand, Grip grip)
		{
			if ((Object)(object)hand == (Object)null || (Object)(object)grip == (Object)null || !HandEmpty(hand))
			{
				return false;
			}
			try
			{
				EndHoverBlend(hand);
				hand.HoveringReceiver = (HandReciever)(object)grip;
				hand.farHoveringReciever = null;
				grip.OnGrabConfirm(hand, true);
			}
			catch
			{
			}
			return HandOnGrip(hand, grip);
		}

		private static char M(ConfigurableJointMotion m)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Invalid comparison between Unknown and I4
			if ((int)m != 0)
			{
				if ((int)m != 1)
				{
					return 'F';
				}
				return 'l';
			}
			return 'L';
		}

		internal static string JointInfo(ConfigurableJoint j)
		{
			//IL_000b: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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)
			try
			{
				return $"{M(j.xMotion)}{M(j.yMotion)}{M(j.zMotion)}/{M(j.angularXMotion)}{M(j.angularYMotion)}{M(j.angularZMotion)}";
			}
			catch
			{
				return "?";
			}
		}

		internal static bool IsLockedHand(IntPtr hand)
		{
			for (int i = 0; i < _locks.Count; i++)
			{
				if (_locks[i].Hand == hand)
				{
					return true;
				}
			}
			return false;
		}

		private static HandLock LockOf(IntPtr hand)
		{
			for (int i = 0; i < _locks.Count; i++)
			{
				if (_locks[i].Hand == hand)
				{
					return _locks[i];
				}
			}
			return null;
		}

		internal static void HoldLock(Well w, Hand hand, InteractableHost gunHost, Rigidbody gunRb, float now)
		{
			//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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			if (w == null || (Object)(object)hand == (Object)null || (Object)(object)gunHost == (Object)null || (Object)(object)gunRb == (Object)null)
			{
				return;
			}
			HandLock handLock = LockOf(((Il2CppObjectBase)hand).Pointer);
			if (handLock != null && handLock.W != w)
			{
				ReleaseLock(handLock, "moved to another gun");
				handLock = null;
			}
			if (handLock == null)
			{
				handLock = new HandLock
				{
					Hand = ((Il2CppObjectBase)hand).Pointer,
					W = w
				};
				_locks.Add(handLock);
			}
			try
			{
				ConfigurableJoint joint = hand.joint;
				if ((Object)(object)joint != (Object)null && (Object)(object)hand.tempJoint == (Object)null && (Object)(object)((Joint)joint).connectedBody != (Object)null && ((Il2CppObjectBase)((Joint)joint).connectedBody).Pointer == ((Il2CppObjectBase)gunRb).Pointer)
				{
					if (((Il2CppObjectBase)joint).Pointer != handLock.JointPtr)
					{
						handLock.Joint = joint;
						handLock.JointPtr = ((Il2CppObjectBase)joint).Pointer;
						handLock.JointSeenAt = now;
						handLock.JointLocked = false;
						handLock.AX = joint.angularXMotion;
						handLock.AY = joint.angularYMotion;
						handLock.AZ = joint.angularZMotion;
					}
					if (now - handLock.JointSeenAt >= 0.1f && ((int)joint.angularXMotion != 0 || (int)joint.angularYMotion != 0 || (int)joint.angularZMotion != 0))
					{
						bool flag = !handLock.JointLocked;
						joint.angularXMotion = (ConfigurableJointMotion)0;
						joint.angularYMotion = (ConfigurableJointMotion)0;
						joint.angularZMotion = (ConfigurableJointMotion)0;
						handLock.JointLocked = true;
						if (L.Tracing)
						{
							L.T("LOCK     '" + Names.Of((Component)(object)w.Socket) + "' wrist locked on the grip " + (flag ? $"{(now - handLock.JointSeenAt) * 1000f:F0} ms after the grab" : "again (something had freed it)"));
						}
					}
				}
			}
			catch
			{
			}
			int num = -1;
			try
			{
				VirtualController virtualController = gunHost.VirtualController;
				if (virtualController != null)
				{
					Grip val = null;
					Hand val2 = null;
					List<HandGripPair> handGripPairs = virtualController.HandGripPairs;
					if (handGripPairs != null)
					{
						for (int i = 0; i < handGripPairs.Count; i++)
						{
							HandGripPair val3 = handGripPairs[i];
							Hand val4 = ((val3 == null) ? null : val3.hand);
							if (!((Object)(object)val4 == (Object)null) && !(((Il2CppObjectBase)val4).Pointer == ((Il2CppObjectBase)hand).Pointer))
							{
								val2 = val4;
								val = val3.grip;
							}
						}
					}
					if ((Object)(object)val2 != (Object)null && ((Il2CppObjectBase)val2).Pointer != ((Il2CppObjectBase)hand).Pointer && IsLockedHand(((Il2CppObjectBase)val2).Pointer))
					{
						num = 2;
					}
					else
					{
						bool flag2 = false;
						try
						{
							HandGripPair priPair = virtualController._priPair;
							Hand val5 = ((priPair == null) ? null : priPair.hand);
							flag2 = (Object)(object)val2 != (Object)null && (Object)(object)val5 != (Object)null && ((Il2CppObjectBase)val5).Pointer == ((Il2CppObjectBase)hand).Pointer;
						}
						catch
						{
						}
						num = (flag2 ? 1 : 0);
					}
					if (num == 2)
					{
						RestoreVc(handLock);
					}
					else
					{
						Want(handLock, virtualController.Settings, num);
						Want(handLock, virtualController.defaultSettings, num);
						if ((Object)(object)val != (Object)null)
						{
							VirtualControllerOverride val6 = null;
							try
							{
								virtualController.GetVirtualControllerOverride(val, ref val6);
							}
							catch
							{
								val6 = null;
							}
							if ((Object)(object)val6 != (Object)null && val6.useTheseSettings)
							{
								Want(handLock, val6.virtualControllerSettings, num);
							}
						}
					}
					if (!Hooks.DesyncHookOk)
					{
						try
						{
							Dictionary<Hand, float> desyncTime = virtualController._desyncTime;
							if (desyncTime != null && desyncTime.ContainsKey(hand))
							{
								desyncTime[hand] = 0f;
							}
						}
						catch
						{
						}
					}
				}
			}
			catch
			{
			}
			if (num != handLock.Role || !handLock.Logged)
			{
				handLock.Role = num;
				handLock.Logged = true;
				if (L.Tracing)
				{
					L.T("LOCK     '" + Names.Of((Component)(object)w.Socket) + "' hand locked in place: aim from " + num switch
					{
						2 => "nobody (both hands held at the mag, solve left alone)", 
						1 => "the other hand (this one was first)", 
						0 => "the other hand", 
						_ => "? (no two-hand solve yet)", 
					} + $", turning axes {(handLock.JointLocked ? "locked" : "lock pending")}, solve settings held={handLock.Saved.Count}, release-on-distance " + (Hooks.DesyncHookOk ? "off" : "held back by resetting its timer"));
				}
			}
		}

		private static void Want(HandLock lk, VirtualControllerSettings s, int role)
		{
			if (s == null)
			{
				return;
			}
			IntPtr pointer;
			try
			{
				pointer = ((Il2CppObjectBase)s).Pointer;
			}
			catch
			{
				return;
			}
			if (pointer == IntPtr.Zero)
			{
				return;
			}
			SavedVc savedVc = null;
			for (int i = 0; i < lk.Saved.Count; i++)
			{
				if (lk.Saved[i].Ptr == pointer)
				{
					savedVc = lk.Saved[i];
					break;
				}
			}
			if (savedVc == null)
			{
				SavedVc savedVc2 = null;
				for (int j = 0; j < _locks.Count; j++)
				{
					if (savedVc2 != null)
					{
						break;
					}
					if (_locks[j] == lk)
					{
						continue;
					}
					for (int k = 0; k < _locks[j].Saved.Count; k++)
					{
						if (_locks[j].Saved[k].Ptr == pointer)
						{
							savedVc2 = _locks[j].Saved[k];
							break;
						}
					}
				}
				try
				{
					savedVc = ((savedVc2 != null) ? new SavedVc
					{
						S = s,
						Ptr = pointer,
						Look = savedVc2.Look,
						Twist = savedVc2.Twist,
						Swing = savedVc2.Swing,
						Pos = savedVc2.Pos,
						SwingLim = savedVc2.SwingLim,
						TwistLim = savedVc2.TwistLim
					} : new SavedVc
					{
						S = s,
						Ptr = pointer,
						Look = s.lookRotationWeight,
						Twist = s.handTwistWeight,
						Swing = s.handSwingWeight,
						Pos = s.positionWeight,
						SwingLim = s.jointSwingLimit,
						TwistLim = s.jointTwistLimit
					});
				}
				catch
				{
					return;
				}
				lk.Saved.Add(savedVc);
			}
			float num = ((role == 1) ? 1f : 0f);
			try
			{
				if (s.lookRotationWeight != 0f)
				{
					s.lookRotationWeight = 0f;
				}
				if (s.handSwingWeight != num)
				{
					s.handSwingWeight = num;
				}
				if (s.handTwistWeight != num)
				{
					s.handTwistWeight = num;
				}
				if (s.positionWeight != num)
				{
					s.positionWeight = num;
				}
				if (s.jointSwingLimit != 0f)
				{
					s.jointSwingLimit = 0f;
				}
				if (s.jointTwistLimit != 0f)
				{
					s.jointTwistLimit = 0f;
				}
			}
			catch
			{
			}
		}

		private static void RestoreVc(HandLock lk)
		{
			for (int i = 0; i < lk.Saved.Count; i++)
			{
				SavedVc savedVc = lk.Saved[i];
				bool flag = false;
				for (int j = 0; j < _locks.Count; j++)
				{
					if (flag)
					{
						break;
					}
					if (_locks[j] == lk)
					{
						continue;
					}
					for (int k = 0; k < _locks[j].Saved.Count; k++)
					{
						if (_locks[j].Saved[k].Ptr == savedVc.Ptr)
						{
							flag = true;
							break;
						}
					}
				}
				if (flag)
				{
					continue;
				}
				try
				{
					VirtualControllerSettings s = savedVc.S;
					if (s != null)
					{
						s.lookRotationWeight = savedVc.Look;
						s.handTwistWeight = savedVc.Twist;
						s.handSwingWeight = savedVc.Swing;
						s.positionWeight = savedVc.Pos;
						s.jointSwingLimit = savedVc.SwingLim;
						s.jointTwistLimit = savedVc.TwistLim;
					}
				}
				catch
				{
				}
			}
			lk.Saved.Clear();
		}

		private static void ReleaseLock(HandLock lk, string why)
		{
			//IL_005b: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			if (lk == null)
			{
				return;
			}
			_locks.Remove(lk);
			RestoreVc(lk);
			try
			{
				Hand val = LocalHandByPtr(lk.Hand);
				ConfigurableJoint val2 = (((Object)(object)val == (Object)null) ? null : val.joint);
				if (lk.JointLocked && (Object)(object)val2 != (Object)null && ((Il2CppObjectBase)val2).Pointer == lk.JointPtr)
				{
					val2.angularXMotion = lk.AX;
					val2.angularYMotion = lk.AY;
					val2.angularZMotion = lk.AZ;
				}
			}
			catch
			{
			}
			if (L.Tracing && lk.W != null)
			{
				L.T($"LOCK-END '{Names.Of((Component)(object)lk.W.Socket)}' ({why})");
			}
		}

		internal static void ReleaseLock(Well w, IntPtr hand, string why)
		{
			if (!(hand == IntPtr.Zero))
			{
				HandLock handLock = LockOf(hand);
				if (handLock != null && (w == null || handLock.W == w))
				{
					ReleaseLock(handLock, why);
				}
			}
		}

		internal static void ReleaseLocksOf(Well w, string why)
		{
			for (int num = _locks.Count - 1; num >= 0; num--)
			{
				if (num < _locks.Count && _locks[num].W == w)
				{
					ReleaseLock(_locks[num], why);
				}
			}
		}

		internal static void ReleaseAllLocks(string why)
		{
			for (int num = _locks.Count - 1; num >= 0; num--)
			{
				if (num < _locks.Count)
				{
					ReleaseLock(_locks[num], why);
				}
			}
		}

		internal static IntPtr GunGripOf(Hand hand, Rigidbody gunRb)
		{
			try
			{
				GameObject val = (((Object)(object)hand == (Object)null) ? null : hand.m_CurrentAttachedGO);
				if ((Object)(object)val == (Object)null || (Object)(object)gunRb == (Object)null)
				{
					return IntPtr.Zero;
				}
				return val.transform.IsChildOf(((Component)gunRb).transform) ? ((Il2CppObjectBase)val).Pointer : IntPtr.Zero;
			}
			catch
			{
				return IntPtr.Zero;
			}
		}

		internal static bool AttachedTo(Hand hand, IntPtr go)
		{
			if ((Object)(object)hand == (Object)null || go == IntPtr.Zero)
			{
				return false;
			}
			try
			{
				GameObject currentAttachedGO = hand.m_CurrentAttachedGO;
				return (Object)(object)currentAttachedGO != (Object)null && ((Il2CppObjectBase)currentAttachedGO).Pointer == go;
			}
			catch
			{
				return false;
			}
		}

		internal static bool HeldOnlyByOthers(InteractableHost host)
		{
			if ((Object)(object)host == (Object)null)
			{
				return false;
			}
			try
			{
				if ((Object)(object)Player.LeftHand == (Object)null && (Object)(object)Player.RightHand == (Object)null)
				{
					return false;
				}
			}
			catch
			{
				return false;
			}
			bool result = false;
			for (int i = 0; i < 2; i++)
			{
				Hand val = null;
				try
				{
					val = host.GetHand(i);
				}
				catch
				{
				}
				if (!((Object)(object)val == (Object)null))
				{
					if ((Object)(object)LocalHandByPtr(((Il2CppObjectBase)val).Pointer) != (Object)null)
					{
						return false;
					}
					result = true;
				}
			}
			return result;
		}

		internal static string HandState(Hand hand)
		{
			//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)
			try
			{
				return ((object)hand.physHand.handPhysState/*cast due to .constrained prefix*/).ToString();
			}
			catch
			{
				return "?";
			}
		}

		internal static Rigidbody BodyOf(Hand hand)
		{
			if ((Object)(object)hand == (Object)null)
			{
				return null;
			}
			Rigidbody val = null;
			try
			{
				val = hand.rb;
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				try
				{
					val = ((Component)hand).GetComponent<Rigidbody>();
				}
				catch
				{
				}
			}
			return val;
		}

		internal static bool ReSeat(Magazine mag)
		{
			Rails.StepRegrips++;
			bool result = false;
			try
			{
				Il2CppArrayBase<Grip> componentsInChildren = ((Component)mag).GetComponentsInChildren<Grip>(true);
				if (componentsInChildren == null)
				{
					return false;
				}
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Grip val = componentsInChildren[i];
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					Hand val2 = null;
					try
					{
						val2 = val.GetHand();
					}
					catch
					{
					}
					if (!((Object)(object)val2 == (Object)null))
					{
						try
						{
							val.ForceDetach(val2);
						}
						catch
						{
							continue;
						}
						try
						{
							val.OnHandHoverBegin(val2, true);
						}
						catch
						{
						}
						try
						{
							val.OnGrabConfirm(val2, true);
						}
						catch
						{
						}
						EndHoverBlend(val2);
						result = true;
					}
				}
			}
			catch
			{
			}
			return result;
		}

		internal static Collider[] SolidColliders(Transform root)
		{
			try
			{
				Il2CppArrayBase<Collider> componentsInChildren = ((Component)root).GetComponentsInChildren<Collider>(true);
				if (componentsInChildren == null)
				{
					return null;
				}
				int num = 0;
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Collider val = componentsInChildren[i];
					if (!((Object)(object)val == (Object)null) && !val.isTrigger)
					{
						num++;
					}
				}
				Collider[] array = (Collider[])(object)new Collider[num];
				int num2 = 0;
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					if (num2 >= num)
					{
						break;
					}
					Collider val2 = componentsInChildren[j];
					if (!((Object)(object)val2 == (Object)null) && !val2.isTrigger)
					{
						array[num2++] = val2;
					}
				}
				return array;
			}
			catch
			{
				return null;
			}
		}

		internal static Hand GunHand(Well w)
		{
			try
			{
				Gun gun = w.Socket.gun;
				if ((Object)(object)gun == (Object)null || (Object)(object)gun.triggerGrip == (Object)null)
				{
					return null;
				}
				return gun.triggerGrip.GetHand();
			}
			catch
			{
				return null;
			}
		}

		internal static IntPtr PtrOf(Hand hand)
		{
			try
			{
				return ((Object)(object)hand == (Object)null) ? IntPtr.Zero : ((Il2CppObjectBase)hand).Pointer;
			}
			catch
			{
				return IntPtr.Zero;
			}
		}

		internal static Collider[] CollectHandColliders(Hand hand)
		{
			try
			{
				if ((Object)(object)hand == (Object)null)
				{
					return null;
				}
				List<Collider> list = new List<Collider>();
				Collider[] array = SolidColliders(((Component)hand).transform);
				if (array != null)
				{
					for (int i = 0; i < array.Length; i++)
					{
						list.Add(array[i]);
					}
				}
				try
				{
					PhysHand physHand = hand.physHand;
					if ((Object)(object)physHand != (Object)null)
					{
						AddSolid(list, (Collider)(object)physHand.handCol);
						AddSolid(list, (Collider)(object)physHand.fingersCol);
						AddSolid(list, (Collider)(object)physHand.cUpper);
						AddSolid(list, (Collider)(object)physHand.cLower);
					}
				}
				catch
				{
				}
				re