Decompiled source of WolverineClaws v1.0.1

Mods/WolverineClaws.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using HarmonyLib;
using Il2Cpp;
using Il2CppActiveRagdoll;
using Il2CppHurricaneVR.Framework.ControllerInput;
using Il2CppHurricaneVR.Framework.Core;
using Il2CppHurricaneVR.Framework.Core.Grabbers;
using Il2CppHurricaneVR.Framework.Core.HandPoser;
using Il2CppHurricaneVR.Framework.Core.Stabbing;
using Il2CppHurricaneVR.Framework.Shared;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using WolverineClaws;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(ClawsMod), "WolverineClaws", "1.0.1", "coope", null)]
[assembly: MelonGame("Kubunautilus", "BrutalistickVR")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("WolverineClaws")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WolverineClaws")]
[assembly: AssemblyTitle("WolverineClaws")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 WolverineClaws
{
	internal static class ClawBlood
	{
		private class Entry
		{
			public Renderer Rend;

			public PaintTarget Target;

			public Material Blood;

			public Material Metal;

			public bool Bloody;
		}

		[HarmonyPatch(typeof(PaintTarget), "PaintObject")]
		private static class PaintObjectPatch
		{
			private static void Prefix(PaintTarget target)
			{
				Mark(target);
			}
		}

		[HarmonyPatch(typeof(PaintTarget), "ForcePaintObject")]
		private static class ForcePaintObjectPatch
		{
			private static void Prefix(PaintTarget target)
			{
				Mark(target);
			}
		}

		[HarmonyPatch(typeof(PaintTarget), "ForcePaintObjectMultiple")]
		private static class ForcePaintObjectMultiplePatch
		{
			private static void Prefix(PaintTarget target)
			{
				Mark(target);
			}
		}

		[HarmonyPatch(typeof(PaintTarget), "ClearAllPaint")]
		private static class ClearAllPaintPatch
		{
			private static void Postfix()
			{
				foreach (Entry value in Targets.Values)
				{
					if ((Object)(object)value.Rend != (Object)null && value.Bloody && (Object)(object)value.Metal != (Object)null)
					{
						value.Rend.sharedMaterial = value.Metal;
						value.Bloody = false;
					}
				}
			}
		}

		private static readonly Dictionary<IntPtr, Entry> Targets = new Dictionary<IntPtr, Entry>();

		public static bool Register(PaintTarget pt, Renderer rend, Material metal, Instance log)
		{
			Prune();
			if ((Object)(object)pt == (Object)null || (Object)(object)rend == (Object)null)
			{
				return false;
			}
			if (!pt.validTarget)
			{
				string name = ((Object)rend).name;
				Material sharedMaterial = rend.sharedMaterial;
				object obj;
				if (sharedMaterial == null)
				{
					obj = null;
				}
				else
				{
					Shader shader = sharedMaterial.shader;
					obj = ((shader != null) ? ((Object)shader).name : null);
				}
				log.Warning(name + ": blood target not valid (material '" + (string?)obj + "')");
				return false;
			}
			if (!pt.setupComplete)
			{
				pt.SetupPaint();
			}
			Material sharedMaterial2 = rend.sharedMaterial;
			Targets[((Il2CppObjectBase)pt).Pointer] = new Entry
			{
				Rend = rend,
				Target = pt,
				Blood = sharedMaterial2,
				Metal = metal
			};
			if ((Object)(object)metal != (Object)null)
			{
				rend.sharedMaterial = metal;
			}
			return true;
		}

		public static void Release(GameObject claws)
		{
			if ((Object)(object)claws == (Object)null)
			{
				return;
			}
			Transform transform = claws.transform;
			foreach (KeyValuePair<IntPtr, Entry> item in Targets.ToList())
			{
				Entry value = item.Value;
				if ((Object)(object)value.Rend == (Object)null || !((Component)value.Rend).transform.IsChildOf(transform))
				{
					continue;
				}
				try
				{
					if ((Object)(object)value.Target != (Object)null)
					{
						value.Target.ReleaseRenderTextures();
					}
				}
				catch
				{
				}
				if ((Object)(object)value.Blood != (Object)null && (Object)(object)value.Blood != (Object)(object)value.Metal)
				{
					Object.Destroy((Object)(object)value.Blood);
				}
				Targets.Remove(item.Key);
			}
		}

		public static bool IsBloody(Renderer rend)
		{
			return Targets.Values.Any((Entry e) => (Object)(object)e.Rend != (Object)null && (Object)(object)e.Rend == (Object)(object)rend && e.Bloody);
		}

		private static void Prune()
		{
			foreach (IntPtr item in (from kv in Targets
				where (Object)(object)kv.Value.Rend == (Object)null
				select kv.Key).ToList())
			{
				Targets.Remove(item);
			}
		}

		private static void Mark(PaintTarget t)
		{
			if (!((Object)(object)t == (Object)null) && Targets.TryGetValue(((Il2CppObjectBase)t).Pointer, out var value) && !value.Bloody && !((Object)(object)value.Rend == (Object)null))
			{
				value.Rend.sharedMaterial = value.Blood;
				value.Bloody = true;
			}
		}
	}
	internal static class ClawSever
	{
		private class Claw
		{
			public GameObject Obj;

			public Rigidbody Rb;

			public Il2CppReferenceArray<Collider> Solid;

			public Transform[] Bottom = (Transform[])(object)new Transform[3];

			public Transform[] Top = (Transform[])(object)new Transform[3];

			public Vector3[] PrevBottom = (Vector3[])(object)new Vector3[3];

			public Vector3[] PrevTop = (Vector3[])(object)new Vector3[3];

			public bool HasPrev;

			public bool[] Near = new bool[3];

			public int Idle;
		}

		private class Track
		{
			public Vector3 Entry;

			public float Seen;

			public string Name;

			public float MinProg = 1f;

			public float MaxSide;

			public float EntryMag;

			public float Half;

			public bool Tip;

			public bool Cut;

			public bool Valid;

			public int Steps;
		}

		private static readonly float MinSpeed = (float.TryParse(Environment.GetEnvironmentVariable("WC_SEVERSPEED"), out var result) ? result : 0.75f);

		public static Instance Log;

		public static int Severed;

		private static readonly List<Claw> Claws = new List<Claw>();

		private static readonly Dictionary<(IntPtr, IntPtr), Track> Tracks = new Dictionary<(IntPtr, IntPtr), Track>();

		private static readonly HashSet<IntPtr> _seenThisStep = new HashSet<IntPtr>();

		private static readonly Dictionary<IntPtr, SliceableObject> _partOf = new Dictionary<IntPtr, SliceableObject>();

		private static bool _anyNear;

		public static bool Disabled
		{
			get
			{
				if (!ClawSharpness.Disabled)
				{
					return Environment.GetEnvironmentVariable("WC_NOSEVER") == "1";
				}
				return true;
			}
		}

		public static void Add(GameObject obj, Instance log)
		{
			if (Log == null)
			{
				Log = log;
			}
			if ((Object)(object)obj == (Object)null)
			{
				return;
			}
			foreach (Claw claw2 in Claws)
			{
				if ((Object)(object)claw2.Obj != (Object)null && ((Il2CppObjectBase)claw2.Obj).Pointer == ((Il2CppObjectBase)obj).Pointer)
				{
					return;
				}
			}
			Claw claw = new Claw
			{
				Obj = obj,
				Rb = obj.GetComponent<Rigidbody>()
			};
			List<Collider> list = new List<Collider>();
			foreach (Collider componentsInChild in obj.GetComponentsInChildren<Collider>(true))
			{
				if ((Object)(object)componentsInChild != (Object)null && !componentsInChild.isTrigger)
				{
					list.Add(componentsInChild);
				}
			}
			claw.Solid = new Il2CppReferenceArray<Collider>(list.ToArray());
			for (int i = 0; i < 3; i++)
			{
				Transform val = obj.transform.Find($"Colliders/Blade{i}");
				claw.Bottom[i] = ((val != null) ? val.Find("SlashPoints/Bottom") : null);
				claw.Top[i] = ((val != null) ? val.Find("SlashPoints/Top") : null);
			}
			Claws.Add(claw);
		}

		private static SliceableObject PartOf(Collider col, Rigidbody self)
		{
			if (_partOf.TryGetValue(((Il2CppObjectBase)col).Pointer, out var value))
			{
				return value;
			}
			if (_partOf.Count > 4000)
			{
				_partOf.Clear();
			}
			Rigidbody attachedRigidbody = col.attachedRigidbody;
			value = (((Object)(object)attachedRigidbody == (Object)null || (Object)(object)attachedRigidbody == (Object)(object)self) ? null : ((Component)col).GetComponentInParent<SliceableObject>());
			_partOf[((Il2CppObjectBase)col).Pointer] = value;
			return value;
		}

		public static void ForgetColliders()
		{
			_partOf.Clear();
		}

		public static void Tick()
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: 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_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			if (Claws.Count == 0)
			{
				return;
			}
			float time = Time.time;
			float fixedDeltaTime = Time.fixedDeltaTime;
			for (int num = Claws.Count - 1; num >= 0; num--)
			{
				Claw claw = Claws[num];
				if ((Object)(object)claw.Obj == (Object)null)
				{
					Claws.RemoveAt(num);
				}
				else
				{
					for (int i = 0; i < 3; i++)
					{
						Transform val = claw.Bottom[i];
						Transform val2 = claw.Top[i];
						if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
						{
							continue;
						}
						Vector3 position = val.position;
						Vector3 position2 = val2.position;
						Vector3 val3 = claw.PrevBottom[i];
						Vector3 val4 = claw.PrevTop[i];
						claw.PrevBottom[i] = position;
						claw.PrevTop[i] = position2;
						if (!claw.HasPrev || Disabled)
						{
							continue;
						}
						Vector3 val5 = position2 - position;
						float magnitude = ((Vector3)(ref val5)).magnitude;
						if (magnitude < 0.0001f)
						{
							continue;
						}
						Vector3 axis = (position2 - position) / magnitude;
						Vector3 val6 = (position + position2 - val3 - val4) * 0.5f;
						_seenThisStep.Clear();
						if (((Vector3)(ref val6)).magnitude < 0.005f && !claw.Near[i] && claw.Idle % 5 != 0)
						{
							continue;
						}
						int num2 = Mathf.Clamp(Mathf.CeilToInt(((Vector3)(ref val6)).magnitude / 0.015f), 1, 10);
						_anyNear = false;
						for (int num3 = num2; num3 >= 1; num3--)
						{
							float num4 = (float)num3 / (float)num2;
							foreach (Collider item in (Il2CppArrayBase<Collider>)(object)Physics.OverlapCapsule(Vector3.Lerp(val3, position, num4), Vector3.Lerp(val4, position2, num4), 0.006f, -1, (QueryTriggerInteraction)1))
							{
								if ((Object)(object)item != (Object)null)
								{
									Consider(claw, i, item, position, position2, val3, val4, magnitude, axis, time, fixedDeltaTime);
								}
							}
						}
						claw.Near[i] = _anyNear;
					}
					claw.HasPrev = true;
					claw.Idle++;
				}
			}
			if (Tracks.Count <= 0)
			{
				return;
			}
			List<(IntPtr, IntPtr)> list = null;
			foreach (KeyValuePair<(IntPtr, IntPtr), Track> track in Tracks)
			{
				if (!(time - track.Value.Seen > 0.15f))
				{
					continue;
				}
				(list ?? (list = new List<(IntPtr, IntPtr)>())).Add(track.Key);
				Track value = track.Value;
				if (ClawSharpness.Tracing && !value.Cut)
				{
					Instance log = Log;
					if (log != null)
					{
						log.Msg($"SEVER no cut {value.Name}: {value.Steps} steps, came in {value.EntryMag * 100f:F1} cm from its middle (surface at {value.Half * 100f:F1} cm{(value.Valid ? "" : ", too close to the middle to count")}), got {(1f - value.MinProg) * 100f:F0}% of the way to/past it (100% = middle), fastest sideways {value.MaxSide:F1} m/s{(value.Tip ? ", tip/base only at times" : "")}");
					}
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (var item2 in list)
			{
				Tracks.Remove(item2);
			}
		}

		private static Vector3 Across(Vector3 centre, Vector3 a, Vector3 b, out float s, out float len)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_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_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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = b - a;
			len = ((Vector3)(ref val)).magnitude;
			Vector3 val2 = ((len > 1E-05f) ? ((b - a) / len) : Vector3.forward);
			s = Mathf.Clamp(Vector3.Dot(centre - a, val2), 0f, len);
			Vector3 val3 = centre - (a + val2 * s);
			return val3 - val2 * Vector3.Dot(val3, val2);
		}

		private static void Consider(Claw c, int i, Collider col, Vector3 p0, Vector3 p1, Vector3 q0, Vector3 q1, float len, Vector3 axis, float now, float dt)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_0081: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: 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_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: 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)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			SliceableObject val = PartOf(col, c.Rb);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			_anyNear = true;
			if (!_seenThisStep.Add(((Il2CppObjectBase)val).Pointer) || !val.canBeSliced || (Object)(object)val.sliceOnInputCustom == (Object)null)
			{
				return;
			}
			Rigidbody attachedRigidbody = col.attachedRigidbody;
			if ((Object)(object)attachedRigidbody == (Object)null)
			{
				return;
			}
			Collider val2 = (((Object)(object)val.mainCollider != (Object)null) ? val.mainCollider : col);
			Bounds bounds = val2.bounds;
			Vector3 center = ((Bounds)(ref bounds)).center;
			float s;
			float len2;
			Vector3 val3 = Across(center, p0, p1, out s, out len2);
			(IntPtr, IntPtr) key = (((Il2CppObjectBase)c.Bottom[i]).Pointer, ((Il2CppObjectBase)val).Pointer);
			if (!Tracks.TryGetValue(key, out var value))
			{
				float len3;
				Vector3 val4 = Across(center, q0, q1, out len2, out len3);
				float num = 0f;
				if (((Vector3)(ref val4)).sqrMagnitude > 1E-08f)
				{
					Vector3 normalized = ((Vector3)(ref val4)).normalized;
					RaycastHit val5 = default(RaycastHit);
					if (val2.Raycast(new Ray(center - normalized * 1f, normalized), ref val5, 1f))
					{
						num = 1f - ((RaycastHit)(ref val5)).distance;
					}
				}
				bool flag = ((Vector3)(ref val4)).magnitude >= Mathf.Max(0.012f, num * 0.4f);
				value = new Track
				{
					Entry = (flag ? val4 : Vector3.zero),
					Valid = flag,
					Name = $"Blade{i} x {((Object)val).name}",
					EntryMag = ((Vector3)(ref val4)).magnitude,
					Half = num
				};
				Tracks[key] = value;
			}
			value.Seen = now;
			value.Steps++;
			if (((Vector3)(ref value.Entry)).sqrMagnitude < 1E-08f)
			{
				return;
			}
			value.MinProg = Mathf.Min(value.MinProg, Vector3.Dot(val3, value.Entry) / ((Vector3)(ref value.Entry)).sqrMagnitude);
			Vector3 val6 = p0 + axis * s;
			Vector3 val7 = q0 + (q1 - q0) * (s / len);
			Vector3 val8 = (val6 - val7) / dt - attachedRigidbody.GetPointVelocity(val6);
			Vector3 side = val8 - axis * Vector3.Dot(val8, axis);
			value.MaxSide = Mathf.Max(value.MaxSide, ((Vector3)(ref side)).magnitude);
			bool flag2 = s <= 0.005f || s >= len - 0.005f;
			if (flag2)
			{
				value.Tip = true;
			}
			if (!(Vector3.Dot(val3, value.Entry) > 0f || flag2))
			{
				if (((Vector3)(ref side)).magnitude < MinSpeed)
				{
					value.Entry = Vector3.zero;
					return;
				}
				value.Entry = Vector3.zero;
				value.Cut = true;
				Cut(c, val, val6, axis, side, val8, attachedRigidbody);
			}
		}

		private static void Cut(Claw c, SliceableObject part, Vector3 at, Vector3 axis, Vector3 side, Vector3 rel, Rigidbody partRb)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.Cross(axis, side);
			if (((Vector3)(ref val)).sqrMagnitude < 1E-08f)
			{
				return;
			}
			Plane val2 = default(Plane);
			((Plane)(ref val2))..ctor(((Vector3)(ref val)).normalized, at);
			string name = ((Object)part).name;
			try
			{
				SliceableBodyPart val3 = ((Il2CppObjectBase)part).TryCast<SliceableBodyPart>();
				if ((Object)(object)val3 != (Object)null)
				{
					((SliceableObject)val3).SliceObject(val2, at, rel, c.Rb, c.Solid, part.directlyConnectedRb, 0.3f);
				}
				else
				{
					part.SliceObject(val2, at, rel, c.Rb, c.Solid, part.directlyConnectedRb, 0.3f);
				}
				Severed++;
				Instance log = Log;
				if (log != null)
				{
					log.Msg($"CLAW cut off '{((Object)((Component)partRb).transform.root).name}/{name}' at {((Vector3)(ref side)).magnitude:F1} m/s");
				}
			}
			catch (Exception ex)
			{
				Instance log2 = Log;
				if (log2 != null)
				{
					log2.Warning("Cutting '" + name + "' failed: " + ex.Message);
				}
			}
		}
	}
	internal static class ClawSharpness
	{
		[HarmonyPatch(typeof(SharpWeaponManager), "HandleCollision")]
		private static class ClawCollision
		{
			private static void Prefix(SharpWeaponManager __instance, Collision collision)
			{
				if (Disabled || (Object)(object)__instance == (Object)null || !ClawManagers.Contains(((Il2CppObjectBase)__instance).Pointer))
				{
					return;
				}
				try
				{
					TraceImpulse(collision);
				}
				catch
				{
				}
				try
				{
					LogContact(collision);
				}
				catch
				{
				}
				try
				{
					CutThroughArmour(collision, __instance);
				}
				catch
				{
				}
				try
				{
					PassThrough(collision, __instance);
				}
				catch
				{
				}
				try
				{
					Soften(collision);
				}
				catch
				{
				}
			}
		}

		[HarmonyPatch(typeof(SharpWeaponManager), "HandleSlashJoints")]
		private static class LoosenAfterStep
		{
			private static void Postfix(SharpWeaponManager __instance)
			{
				try
				{
					Loosen(__instance);
				}
				catch
				{
				}
			}
		}

		[HarmonyPatch(typeof(SharpWeaponManager), "HandleSlashJointCreation")]
		private static class LoosenAfterCreate
		{
			private static void Postfix(SharpWeaponManager __instance)
			{
				try
				{
					Loosen(__instance);
				}
				catch
				{
				}
			}
		}

		private class Pass
		{
			public SharpWeaponManager Claws;

			public Rigidbody Part;

			public Collider[] Mine;

			public Collider[] Theirs;

			public float LastNear;
		}

		[HarmonyPatch(typeof(SharpWeaponManager), "AssignNewJointValues")]
		private static class LoosenAfterAssign
		{
			private static void Postfix(SharpWeaponManager __instance)
			{
				try
				{
					Loosen(__instance);
				}
				catch
				{
				}
			}
		}

		[HarmonyPatch(typeof(SharpWeaponManager), "ForceLockJointOnAxes")]
		private static class LoosenAfterLock
		{
			private static void Postfix(SharpWeaponManager __instance)
			{
				try
				{
					Loosen(__instance);
				}
				catch
				{
				}
			}
		}

		[HarmonyPatch(typeof(SliceableBodyPart), "ObjectSlashed")]
		private static class BodySlashed
		{
			private static void Prefix()
			{
				Slashes++;
			}
		}

		[HarmonyPatch(typeof(SliceableBodyPart), "SliceObject")]
		private static class BodySliced
		{
			private static void Prefix(SliceableBodyPart __instance)
			{
				Slices++;
				if (Tracing)
				{
					Instance log = Log;
					if (log != null)
					{
						log.Msg("SEVERED '" + ((__instance != null) ? ((Object)__instance).name : null) + "'");
					}
				}
			}
		}

		private const float CoverageToSever = 0.2f;

		private static readonly float ResistanceScale = (float.TryParse(Environment.GetEnvironmentVariable("WC_BODYSCALE"), out var result) ? result : 0.02f);

		private static readonly HashSet<IntPtr> ClawManagers = new HashSet<IntPtr>();

		private static readonly HashSet<IntPtr> Softened = new HashSet<IntPtr>();

		private static readonly HashSet<IntPtr> Armour = new HashSet<IntPtr>();

		public static Instance Log;

		private static readonly HashSet<IntPtr> Logged = new HashSet<IntPtr>();

		public static bool Tracing;

		public static readonly Dictionary<string, float> Impulses = new Dictionary<string, float>();

		private static readonly float Hold = (float.TryParse(Environment.GetEnvironmentVariable("WC_HOLD"), out var result2) ? result2 : 0f);

		private static bool _loggedLoosen;

		private static readonly Dictionary<(IntPtr, IntPtr), Pass> Passing = new Dictionary<(IntPtr, IntPtr), Pass>();

		public static int Slashes;

		public static int Slices;

		public static bool Disabled => Environment.GetEnvironmentVariable("WC_OLDSHARP") == "1";

		public static int SoftenedCount => Softened.Count;

		public static int PassingCount => Passing.Count;

		public static void Apply(GameObject claws, Instance log)
		{
			//IL_0074: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			if (Log == null)
			{
				Log = log;
			}
			if (Disabled || (Object)(object)claws == (Object)null)
			{
				return;
			}
			SharpWeaponManager component = claws.GetComponent<SharpWeaponManager>();
			if ((Object)(object)component == (Object)null)
			{
				log.Warning("No SharpWeaponManager on the claws; sharpness not applied");
				return;
			}
			component.canRunThrough = true;
			component.stabRequiredImpulseMagnitude = 0.1f;
			component.slashRequiredImpulseMagnitude = 0.15f;
			component.slashingThreshold = 0f;
			component.isSlashDualSided = true;
			component.slashForwardAngleRange = new Vector2(85f, 89.9f);
			component.slashUpAngleRange = new Vector2(85f, 89.9f);
			component.stabAngleRange = new Vector2(85f, 89.9f);
			SlashingSharpnessScriptableObject slashingSharpnessData = component.slashingSharpnessData;
			if ((Object)(object)slashingSharpnessData != (Object)null)
			{
				slashingSharpnessData.frictionCoefficient = 0.02f;
				slashingSharpnessData.flatStabFrictionMultiplier = 0.05f;
				slashingSharpnessData.stabDepthForMaxStabMultiplier = 0.01f;
				slashingSharpnessData.minimumChopSpring = 0.5f;
				slashingSharpnessData.maximumChopSpring = 5f;
				slashingSharpnessData.minimumStabSpring = 0.1f;
				slashingSharpnessData.maximumStabSpring = 1f;
				slashingSharpnessData.chopLockVelocityThreshold = 100f;
				slashingSharpnessData.chopUnlockForceThreshold = 1f;
				slashingSharpnessData.chopInstantUnlockForceThreshold = 2f;
				slashingSharpnessData.stabLockVelocityThreshold = 100f;
				slashingSharpnessData.stabUnlockForceThreshold = 1f;
				slashingSharpnessData.stabInstantUnlockForceThreshold = 2f;
				slashingSharpnessData.useStabOutsideLockForces = true;
				slashingSharpnessData.stabUnlockOutsideForceThreshold = 1f;
				slashingSharpnessData.stabInstantUnlockOutsideForceThreshold = 2f;
			}
			else
			{
				log.Warning("Claws have no cutting profile; only partial sharpness applied");
			}
			if ((Object)(object)slashingSharpnessData != (Object)null)
			{
				if (float.TryParse(Environment.GetEnvironmentVariable("WC_LOCKVEL"), out var result))
				{
					slashingSharpnessData.stabLockVelocityThreshold = result;
					slashingSharpnessData.chopLockVelocityThreshold = result;
				}
				if (float.TryParse(Environment.GetEnvironmentVariable("WC_UNLOCK"), out var result2))
				{
					slashingSharpnessData.stabUnlockForceThreshold = result2;
					slashingSharpnessData.stabInstantUnlockForceThreshold = result2 * 2f;
					slashingSharpnessData.chopUnlockForceThreshold = result2;
					slashingSharpnessData.chopInstantUnlockForceThreshold = result2 * 2f;
					slashingSharpnessData.stabUnlockOutsideForceThreshold = result2;
					slashingSharpnessData.stabInstantUnlockOutsideForceThreshold = result2 * 2f;
				}
				if (float.TryParse(Environment.GetEnvironmentVariable("WC_SPRING"), out var result3))
				{
					slashingSharpnessData.minimumStabSpring = result3 * 0.1f;
					slashingSharpnessData.maximumStabSpring = result3;
					slashingSharpnessData.minimumChopSpring = result3 * 0.1f;
					slashingSharpnessData.maximumChopSpring = result3;
				}
				if (float.TryParse(Environment.GetEnvironmentVariable("WC_FRICTION"), out var result4))
				{
					slashingSharpnessData.frictionCoefficient = result4;
				}
			}
			SlicerWeaponController component2 = claws.GetComponent<SlicerWeaponController>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.sliceThreshold = 0f;
				component2.continueSliceThreshold = 0f;
				component2.slicePower = 3;
			}
			ClawManagers.Add(((Il2CppObjectBase)component).Pointer);
		}

		private static void CutThroughArmour(Collision c, SharpWeaponManager claws)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			Collider collider = c.collider;
			if ((Object)(object)collider == (Object)null)
			{
				return;
			}
			ArmorPiece componentInParent = ((Component)collider).GetComponentInParent<ArmorPiece>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return;
			}
			foreach (Collider componentsInChild in ((Component)claws).GetComponentsInChildren<Collider>())
			{
				foreach (Collider componentsInChild2 in ((Component)componentInParent).GetComponentsInChildren<Collider>())
				{
					Physics.IgnoreCollision(componentsInChild, componentsInChild2, true);
				}
			}
			if (!Armour.Add(((Il2CppObjectBase)componentInParent).Pointer))
			{
				return;
			}
			Vector3 val;
			if (c.contactCount <= 0)
			{
				Bounds bounds = collider.bounds;
				val = ((Bounds)(ref bounds)).center;
			}
			else
			{
				ContactPoint contact = c.GetContact(0);
				val = ((ContactPoint)(ref contact)).point;
			}
			Vector3 val2 = val;
			try
			{
				componentInParent.armorHealth = 0;
				if ((Object)(object)componentInParent.fracOnInput != (Object)null)
				{
					componentInParent.fracOnInput.ForceFracture(val2);
				}
			}
			catch
			{
			}
			Instance log = Log;
			if (log != null)
			{
				log.Msg("CLAW cut through armour '" + ((Object)componentInParent).name + "'");
			}
		}

		private static void LogContact(Collision c)
		{
			Rigidbody val = ((c != null) ? c.rigidbody : null);
			Collider val2 = ((c != null) ? c.collider : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			IntPtr item = (((Object)(object)val != (Object)null) ? ((Il2CppObjectBase)val).Pointer : ((Il2CppObjectBase)val2).Pointer);
			if (!Logged.Add(item) || Logged.Count > 400)
			{
				return;
			}
			SliceableObject val3 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInParent<SliceableObject>() : null);
			object obj;
			if (!((Object)(object)((Component)val2).GetComponentInParent<ArmorPiece>() != (Object)null))
			{
				if (!((Object)(object)val3 != (Object)null))
				{
					obj = "not cuttable";
				}
				else
				{
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 3);
					defaultInterpolatedStringHandler.AppendLiteral("flesh '");
					defaultInterpolatedStringHandler.AppendFormatted(((Object)val3).name);
					defaultInterpolatedStringHandler.AppendLiteral("' coverage=");
					defaultInterpolatedStringHandler.AppendFormatted(val3.sliceCoverageToProcSlice, "F2");
					defaultInterpolatedStringHandler.AppendLiteral(" settings='");
					SliceableObjectSettings sliceableObjectSettings = val3.sliceableObjectSettings;
					defaultInterpolatedStringHandler.AppendFormatted((sliceableObjectSettings != null) ? ((Object)sliceableObjectSettings).name : null);
					defaultInterpolatedStringHandler.AppendLiteral("'");
					obj = defaultInterpolatedStringHandler.ToStringAndClear();
				}
			}
			else
			{
				obj = "ARMOUR";
			}
			string value = (string)obj;
			Instance log = Log;
			if (log != null)
			{
				log.Msg($"CLAW hit '{((Object)((Component)val2).transform.root).name}/{((Object)val2).name}': {value}");
			}
		}

		private static void Soften(Collision c)
		{
			Rigidbody val = ((c != null) ? c.rigidbody : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			SliceableObject val2 = ((Component)val).GetComponent<SliceableObject>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = ((Component)val).GetComponentInParent<SliceableObject>();
			}
			if (!((Object)(object)val2 == (Object)null) && Softened.Add(((Il2CppObjectBase)val2).Pointer))
			{
				if (val2.sliceCoverageToProcSlice > 0.2f)
				{
					val2.sliceCoverageToProcSlice = 0.2f;
				}
				SliceableObjectSettings sliceableObjectSettings = val2.sliceableObjectSettings;
				if ((Object)(object)sliceableObjectSettings != (Object)null)
				{
					SliceableObjectSettings val3 = Object.Instantiate<SliceableObjectSettings>(sliceableObjectSettings);
					((Object)val3).name = ((Object)sliceableObjectSettings).name + " (claw-softened)";
					val3.frictionForce1 *= ResistanceScale;
					val3.frictionForce2 *= ResistanceScale;
					val3.chopMaxFrictionForce *= ResistanceScale;
					val3.stabMaxFrictionForce *= ResistanceScale;
					val2.sliceableObjectSettings = val3;
				}
			}
		}

		private static void TraceImpulse(Collision c)
		{
			//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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			if (Tracing && c != null && !((Object)(object)c.collider == (Object)null))
			{
				object obj;
				if (c.contactCount <= 0)
				{
					obj = "?";
				}
				else
				{
					ContactPoint contact = c.GetContact(0);
					Collider thisCollider = ((ContactPoint)(ref contact)).thisCollider;
					obj = ((thisCollider != null) ? ((Object)thisCollider).name : null);
				}
				string value = (string)obj;
				string key = $"{value} x '{((Object)((Component)c.collider).transform.root).name}/{((Object)c.collider).name}' (layer {LayerMask.LayerToName(((Component)c.collider).gameObject.layer)})";
				Impulses.TryGetValue(key, out var value2);
				Dictionary<string, float> impulses = Impulses;
				float num = value2;
				Vector3 impulse = c.impulse;
				impulses[key] = num + ((Vector3)(ref impulse)).magnitude;
			}
		}

		private static void Loosen(SharpWeaponManager swm)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			if (Disabled || Environment.GetEnvironmentVariable("WC_NOLOOSEN") == "1" || (Object)(object)swm == (Object)null || !ClawManagers.Contains(((Il2CppObjectBase)swm).Pointer))
			{
				return;
			}
			List<SlashJointInfo> slashInfos = swm.slashInfos;
			if (slashInfos == null)
			{
				return;
			}
			JointDrive val = default(JointDrive);
			((JointDrive)(ref val)).positionSpring = 0f;
			((JointDrive)(ref val)).positionDamper = Hold;
			((JointDrive)(ref val)).maximumForce = ((Hold > 0f) ? float.MaxValue : 0f);
			JointDrive val2 = val;
			for (int i = 0; i < slashInfos.Count; i++)
			{
				SlashJointInfo obj = slashInfos[i];
				ConfigurableJoint val3 = ((obj != null) ? obj.slashStickyJoint : null);
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				val3.xMotion = (ConfigurableJointMotion)2;
				val3.yMotion = (ConfigurableJointMotion)2;
				val3.zMotion = (ConfigurableJointMotion)2;
				val3.angularXMotion = (ConfigurableJointMotion)2;
				val3.angularYMotion = (ConfigurableJointMotion)2;
				val3.angularZMotion = (ConfigurableJointMotion)2;
				val3.xDrive = val2;
				val3.yDrive = val2;
				val3.zDrive = val2;
				val3.angularXDrive = val2;
				val3.angularYZDrive = val2;
				val3.slerpDrive = val2;
				if (!_loggedLoosen)
				{
					_loggedLoosen = true;
					Instance log = Log;
					if (log != null)
					{
						log.Msg("CLAW joint loosened: claws pass through");
					}
				}
			}
		}

		private static Collider[] Blades(SharpWeaponManager claws)
		{
			List<Collider> list = new List<Collider>();
			foreach (Collider componentsInChild in ((Component)claws).GetComponentsInChildren<Collider>(true))
			{
				if ((Object)(object)componentsInChild != (Object)null && !componentsInChild.isTrigger && ((Object)componentsInChild).name != "Handle")
				{
					list.Add(componentsInChild);
				}
			}
			return list.ToArray();
		}

		private static void PassThrough(Collision c, SharpWeaponManager claws)
		{
			//IL_0053: 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_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_0302: 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)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			if (Environment.GetEnvironmentVariable("WC_NOPASS") == "1")
			{
				return;
			}
			Rigidbody rigidbody = c.rigidbody;
			if ((Object)(object)rigidbody == (Object)null || (Object)(object)((Component)rigidbody).GetComponentInParent<SliceableObject>() == (Object)null || (Object)(object)((Component)c.collider).GetComponentInParent<ArmorPiece>() != (Object)null)
			{
				return;
			}
			bool flag = false;
			ContactPoint contact;
			for (int i = 0; i < c.contactCount; i++)
			{
				contact = c.GetContact(i);
				Collider thisCollider = ((ContactPoint)(ref contact)).thisCollider;
				if ((Object)(object)thisCollider != (Object)null && ((Object)thisCollider).name != "Handle")
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return;
			}
			(IntPtr, IntPtr) key = (((Il2CppObjectBase)claws).Pointer, ((Il2CppObjectBase)rigidbody).Pointer);
			Collider[] mine;
			if (Passing.TryGetValue(key, out var value))
			{
				value.LastNear = Time.time;
				contact = c.GetContact(0);
				if (Physics.GetIgnoreCollision(((ContactPoint)(ref contact)).thisCollider, c.collider))
				{
					return;
				}
				mine = value.Mine;
				foreach (Collider val in mine)
				{
					Collider[] theirs = value.Theirs;
					foreach (Collider val2 in theirs)
					{
						if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
						{
							Physics.IgnoreCollision(val, val2, true);
						}
					}
				}
				if (Tracing)
				{
					Instance log = Log;
					if (log != null)
					{
						log.Msg("CLAW re-ignored '" + ((Object)rigidbody).name + "' (collision had come back)");
					}
				}
				return;
			}
			List<Collider> list = new List<Collider>();
			foreach (Collider componentsInChild in ((Component)rigidbody).GetComponentsInChildren<Collider>())
			{
				if ((Object)(object)componentsInChild != (Object)null && !componentsInChild.isTrigger && (Object)(object)componentsInChild.attachedRigidbody == (Object)(object)rigidbody)
				{
					list.Add(componentsInChild);
				}
			}
			if (!list.Contains(c.collider))
			{
				list.Add(c.collider);
			}
			value = new Pass
			{
				Claws = claws,
				Part = rigidbody,
				Mine = Blades(claws),
				Theirs = list.ToArray(),
				LastNear = Time.time
			};
			mine = value.Mine;
			foreach (Collider val3 in mine)
			{
				Collider[] theirs = value.Theirs;
				foreach (Collider val4 in theirs)
				{
					Physics.IgnoreCollision(val3, val4, true);
				}
			}
			Passing[key] = value;
			if (Tracing)
			{
				Instance log2 = Log;
				if (log2 != null)
				{
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(84, 5);
					defaultInterpolatedStringHandler.AppendLiteral("CLAW passing through '");
					defaultInterpolatedStringHandler.AppendFormatted(((Object)rigidbody).name);
					defaultInterpolatedStringHandler.AppendLiteral("' (");
					defaultInterpolatedStringHandler.AppendFormatted(value.Mine.Length);
					defaultInterpolatedStringHandler.AppendLiteral(" claw colliders x ");
					defaultInterpolatedStringHandler.AppendFormatted(value.Theirs.Length);
					defaultInterpolatedStringHandler.AppendLiteral(" of its colliders; hit by ");
					contact = c.GetContact(0);
					Collider thisCollider2 = ((ContactPoint)(ref contact)).thisCollider;
					defaultInterpolatedStringHandler.AppendFormatted((thisCollider2 != null) ? ((Object)thisCollider2).name : null);
					defaultInterpolatedStringHandler.AppendLiteral(", ignored now=");
					contact = c.GetContact(0);
					defaultInterpolatedStringHandler.AppendFormatted(Physics.GetIgnoreCollision(((ContactPoint)(ref contact)).thisCollider, c.collider));
					defaultInterpolatedStringHandler.AppendLiteral(")");
					log2.Msg(defaultInterpolatedStringHandler.ToStringAndClear());
				}
			}
		}

		public static void Tick()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if (Passing.Count == 0)
			{
				return;
			}
			List<(IntPtr, IntPtr)> list = null;
			foreach (KeyValuePair<(IntPtr, IntPtr), Pass> item in Passing)
			{
				Pass value = item.Value;
				bool flag = (Object)(object)value.Claws == (Object)null || (Object)(object)value.Part == (Object)null;
				if (!flag)
				{
					bool flag2 = false;
					Collider[] mine = value.Mine;
					foreach (Collider val in mine)
					{
						if ((Object)(object)val == (Object)null)
						{
							continue;
						}
						Bounds bounds = val.bounds;
						((Bounds)(ref bounds)).Expand(0.06f);
						Collider[] theirs = value.Theirs;
						foreach (Collider val2 in theirs)
						{
							if ((Object)(object)val2 != (Object)null && ((Bounds)(ref bounds)).Intersects(val2.bounds))
							{
								flag2 = true;
								break;
							}
						}
						if (flag2)
						{
							break;
						}
					}
					if (flag2)
					{
						value.LastNear = Time.time;
					}
					else if (Time.time - value.LastNear > 0.2f)
					{
						mine = value.Mine;
						foreach (Collider val3 in mine)
						{
							Collider[] theirs = value.Theirs;
							foreach (Collider val4 in theirs)
							{
								if ((Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null)
								{
									Physics.IgnoreCollision(val3, val4, false);
								}
							}
						}
						if (Tracing)
						{
							Instance log = Log;
							if (log != null)
							{
								log.Msg("CLAW clear of '" + ((Object)value.Part).name + "', collision back");
							}
						}
						flag = true;
					}
				}
				if (flag)
				{
					(list ?? (list = new List<(IntPtr, IntPtr)>())).Add(item.Key);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (var item2 in list)
			{
				Passing.Remove(item2);
			}
		}

		public static void ResetCounters()
		{
			Slashes = 0;
			Slices = 0;
		}
	}
	public class ClawsMod : MelonMod
	{
		private class Side
		{
			public bool Left;

			public HVRHandGrabber Hand;

			public GameObject Claws;

			public HVRGrabbable Grabbable;

			public bool AutoChecked;

			public bool PrevTrigger;

			public int Button = -1;

			public bool Anchored;

			public Transform AnchorRef;

			public Vector3[] AnchorPos = (Vector3[])(object)new Vector3[3];

			public Quaternion[] AnchorRot = (Quaternion[])(object)new Quaternion[3];

			public Vector3 AnchorDir;

			public float AnchorSpan;

			public float Slide;

			public int Corrections;

			public int BaseJoints;

			public int SkippedInCut;
		}

		private enum ClawBtn
		{
			BY,
			AX,
			Menu,
			Trackpad,
			StickClick,
			FistTrigger,
			KeyboardOnly
		}

		private struct ClawAnchor
		{
			public Vector3[] Base;

			public Quaternion[] Rot;

			public Vector3 Dir;

			public float Span;

			public Vector3 Centre;

			public Vector3 Axis;

			public Vector3 Dorsal;

			public Transform Ref;

			public float Curl;
		}

		private const float GripThreshold = 0.6f;

		private const float TriggerThreshold = 0.6f;

		private readonly Side _left = new Side
		{
			Left = true
		};

		private readonly Side _right = new Side
		{
			Left = false
		};

		private float _nextHandSearch;

		private MeleeScriptableObject _baseSo;

		private MelonPreferences_Category _cat;

		private MelonPreferences_Entry<float> _clawLength;

		private MelonPreferences_Entry<float> _clawSpacing;

		private MelonPreferences_Entry<float> _knuckleOffset;

		private MelonPreferences_Entry<float> _clawYaw;

		private MelonPreferences_Entry<float> _clawPitch;

		private MelonPreferences_Entry<float> _clawSplay;

		private MelonPreferences_Entry<bool> _requireGrip;

		private MelonPreferences_Entry<bool> _debugDump;

		private MelonPreferences_Entry<bool> _inputDebug;

		private MelonPreferences_Entry<bool> _anchorToKnuckles;

		private MelonPreferences_Entry<Key> _keyLeft;

		private MelonPreferences_Entry<Key> _keyRight;

		private readonly bool _perfOnly = Environment.GetEnvironmentVariable("WC_PERFONLY") == "1";

		private readonly bool _perf = Environment.GetEnvironmentVariable("WC_PERF") == "1";

		private readonly Stopwatch _sw = new Stopwatch();

		private double _perfModMs;

		private double _perfWorst;

		private int _perfFrames;

		private float _perfT;

		private int _tickWarnings;

		private double _perfFixedMs;

		private int _perfSteps;

		private readonly Stopwatch _swFixed = new Stopwatch();

		private readonly bool _autoTest = Environment.GetEnvironmentVariable("WC_AUTOTEST") == "1";

		private bool _autoDone;

		private bool _scenesListed;

		private float _autoAt;

		private MelonPreferences_Entry<string> _clawButton;

		private const float KnuckleLift = -0.02f;

		private const float RootSink = 0.05f;

		private readonly bool _noLock = Environment.GetEnvironmentVariable("WC_NOLOCK") == "1";

		private readonly bool _oldSharp = Environment.GetEnvironmentVariable("WC_OLDSHARP") == "1";

		private readonly bool _oldStab = Environment.GetEnvironmentVariable("WC_OLDSTAB") == "1";

		private bool _swingActive;

		private float _renderedWorstD;

		private float _renderedWorstA;

		private int _renderedSamples;

		private readonly bool _photo = Environment.GetEnvironmentVariable("WC_PHOTO") == "1";

		private readonly bool _bloodTest = Environment.GetEnvironmentVariable("WC_BLOODTEST") == "1";

		private readonly bool _driveTest;

		private readonly bool _slashTest;

		private readonly bool _hitTest;

		private readonly bool _swingTest;

		private int _shotW;

		private int _shotH;

		private static string ShotDir => Environment.GetEnvironmentVariable("WC_SHOTDIR") ?? Path.Combine(MelonEnvironment.UserDataDirectory, "WolverineClaws");

		private void DumpInputMap()
		{
			StringBuilder stringBuilder = new StringBuilder();
			IntPtr intPtr = IntPtr.Zero;
			foreach (ProcessModule module in Process.GetCurrentProcess().Modules)
			{
				if (module.ModuleName.Equals("GameAssembly.dll", StringComparison.OrdinalIgnoreCase))
				{
					intPtr = module.BaseAddress;
				}
			}
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(18, 1, stringBuilder2);
			handler.AppendLiteral("GameAssembly base ");
			handler.AppendFormatted(intPtr.ToInt64(), "X");
			stringBuilder3.AppendLine(ref handler);
			BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.NonPublic;
			Assembly[] array = new Assembly[2]
			{
				typeof(MeleeWeaponWrapper).Assembly,
				typeof(HVRController).Assembly
			};
			for (int i = 0; i < array.Length; i++)
			{
				Type[] types = array[i].GetTypes();
				foreach (Type type in types)
				{
					FieldInfo[] fields = type.GetFields(bindingAttr);
					foreach (FieldInfo fieldInfo in fields)
					{
						try
						{
							if (fieldInfo.FieldType != typeof(IntPtr))
							{
								continue;
							}
							IntPtr intPtr2 = (IntPtr)fieldInfo.GetValue(null);
							if (intPtr2 == IntPtr.Zero)
							{
								continue;
							}
							if (fieldInfo.Name.StartsWith("NativeMethodInfoPtr_"))
							{
								IntPtr intPtr3 = Marshal.ReadIntPtr(intPtr2);
								if (intPtr3 != IntPtr.Zero && intPtr != IntPtr.Zero)
								{
									stringBuilder2 = stringBuilder;
									StringBuilder stringBuilder4 = stringBuilder2;
									handler = new StringBuilder.AppendInterpolatedStringHandler(4, 3, stringBuilder2);
									handler.AppendLiteral("M ");
									handler.AppendFormatted(6442450944L + (intPtr3.ToInt64() - intPtr.ToInt64()), "X");
									handler.AppendLiteral(" ");
									handler.AppendFormatted(type.FullName);
									handler.AppendLiteral(".");
									handler.AppendFormatted(fieldInfo.Name.Substring(20));
									stringBuilder4.AppendLine(ref handler);
								}
							}
							else if (fieldInfo.Name.StartsWith("NativeFieldInfoPtr_"))
							{
								uint value = IL2CPP.il2cpp_field_get_offset(intPtr2);
								stringBuilder2 = stringBuilder;
								StringBuilder stringBuilder5 = stringBuilder2;
								handler = new StringBuilder.AppendInterpolatedStringHandler(5, 3, stringBuilder2);
								handler.AppendLiteral("F ");
								handler.AppendFormatted(type.FullName);
								handler.AppendLiteral(" +");
								handler.AppendFormatted(value);
								handler.AppendLiteral(" ");
								handler.AppendFormatted(fieldInfo.Name.Substring(19));
								stringBuilder5.AppendLine(ref handler);
							}
						}
						catch
						{
						}
					}
				}
			}
			Directory.CreateDirectory(ShotDir);
			File.WriteAllText(Path.Combine(ShotDir, "inputmap.txt"), stringBuilder.ToString());
			((MelonBase)this).LoggerInstance.Msg("INPUTMAP written");
		}

		private void ScanButtonEvents(string scene)
		{
			StringBuilder stringBuilder = new StringBuilder("BUTTONSCAN " + scene + "\n");
			foreach (MonoBehaviour item in Resources.FindObjectsOfTypeAll<MonoBehaviour>())
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				string name = ((MemberInfo)((Object)item).GetIl2CppType()).Name;
				if (!name.EndsWith("ButtonEvents") && !name.Contains("ButtonEvent"))
				{
					switch (name)
					{
					case "TimeStopController":
					case "ForceGrabToggle":
					case "NightLightToggle":
					case "PlayerKickManager":
					case "HVRInputModule":
						break;
					default:
						continue;
					}
				}
				string text = ((Object)((Component)item).gameObject).name;
				Transform parent = ((Component)item).transform.parent;
				while ((Object)(object)parent != (Object)null)
				{
					text = ((Object)parent).name + "/" + text;
					parent = parent.parent;
				}
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder3 = stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(19, 3, stringBuilder2);
				handler.AppendLiteral("  ");
				handler.AppendFormatted(name);
				handler.AppendLiteral(" on '");
				handler.AppendFormatted(text);
				handler.AppendLiteral("' (active=");
				handler.AppendFormatted(((Component)item).gameObject.activeInHierarchy);
				handler.AppendLiteral(")\n");
				stringBuilder3.Append(ref handler);
				foreach (FieldInfo item2 in (Il2CppArrayBase<FieldInfo>)(object)((Object)item).GetIl2CppType().GetFields((BindingFlags)52))
				{
					try
					{
						if (!((MemberInfo)item2.FieldType).Name.Contains("Event"))
						{
							continue;
						}
						Object value = item2.GetValue((Object)(object)item);
						UnityEventBase val = ((value != null) ? ((Il2CppObjectBase)value).TryCast<UnityEventBase>() : null);
						if (val != null)
						{
							int persistentEventCount = val.GetPersistentEventCount();
							for (int i = 0; i < persistentEventCount; i++)
							{
								Object persistentTarget = val.GetPersistentTarget(i);
								stringBuilder2 = stringBuilder;
								StringBuilder stringBuilder4 = stringBuilder2;
								handler = new StringBuilder.AppendInterpolatedStringHandler(12, 3, stringBuilder2);
								handler.AppendLiteral("      ");
								handler.AppendFormatted(((MemberInfo)item2).Name);
								handler.AppendLiteral(" -> ");
								handler.AppendFormatted((persistentTarget != (Object)null) ? (((MemberInfo)((Object)persistentTarget).GetIl2CppType()).Name + "('" + persistentTarget.name + "')") : "null");
								handler.AppendLiteral(".");
								handler.AppendFormatted(val.GetPersistentMethodName(i));
								handler.AppendLiteral("\n");
								stringBuilder4.Append(ref handler);
							}
						}
					}
					catch
					{
					}
				}
			}
			((MelonBase)this).LoggerInstance.Msg(stringBuilder.ToString());
		}

		private static string Props(object o, string filter = null)
		{
			if (o == null)
			{
				return "null";
			}
			StringBuilder stringBuilder = new StringBuilder();
			PropertyInfo[] properties = o.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
			foreach (PropertyInfo propertyInfo in properties)
			{
				Type propertyType = propertyInfo.PropertyType;
				if ((propertyType.IsPrimitive || propertyType.IsEnum || propertyType == typeof(Vector2) || propertyType == typeof(Vector3) || propertyType == typeof(string)) && (filter == null || Regex.IsMatch(propertyInfo.Name, filter)))
				{
					try
					{
						StringBuilder stringBuilder2 = stringBuilder;
						StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 2, stringBuilder2);
						handler.AppendLiteral(" ");
						handler.AppendFormatted(propertyInfo.Name);
						handler.AppendLiteral("=");
						handler.AppendFormatted<object>(propertyInfo.GetValue(o));
						stringBuilder2.Append(ref handler);
					}
					catch
					{
					}
				}
			}
			return stringBuilder.ToString();
		}

		private void DumpSharpness(string tag)
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0637: Unknown result type (might be due to invalid IL or missing references)
			//IL_0643: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder("SHARPDUMP " + tag + "\n");
			HashSet<IntPtr> hashSet = new HashSet<IntPtr>();
			foreach (MeleeWeaponWrapper item in Resources.FindObjectsOfTypeAll<MeleeWeaponWrapper>())
			{
				if ((Object)(object)item == (Object)null || (Object)(object)item.meleeWeaponSO == (Object)null)
				{
					continue;
				}
				MeleeScriptableObject meleeWeaponSO = item.meleeWeaponSO;
				if (!hashSet.Add(((Il2CppObjectBase)meleeWeaponSO).Pointer) && !((Object)item).name.Contains("Wolverine"))
				{
					continue;
				}
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder3 = stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(18, 3, stringBuilder2);
				handler.AppendLiteral("== ");
				handler.AppendFormatted(((Object)item).name);
				handler.AppendLiteral(" (SO '");
				handler.AppendFormatted(((Object)meleeWeaponSO).name);
				handler.AppendLiteral("' type=");
				handler.AppendFormatted<MeleeWeaponType>(meleeWeaponSO.meleeWeaponType);
				handler.AppendLiteral(")\n");
				stringBuilder3.Append(ref handler);
				stringBuilder.Append("   SO:" + Props(meleeWeaponSO) + "\n");
				stringBuilder.Append("   wrapper:" + Props(item) + $" slashLines={((item.slashLines != null) ? ((Il2CppArrayBase<SlashLineInfo>)(object)item.slashLines).Length : (-1))} bladeColliders={((item.bladeColliders != null) ? ((Il2CppArrayBase<GameObject>)(object)item.bladeColliders).Length : (-1))}\n");
				SharpWeaponManager component = ((Component)item).GetComponent<SharpWeaponManager>();
				if ((Object)(object)component != (Object)null)
				{
					stringBuilder.Append("   SharpWeaponManager:" + Props(component, "Required|Threshold|canSlash|isSlash|isStab|AngleRange|slashDistance|Multiplier|flat|canRunThrough|tipAndBottom") + "\n");
					SlashingSharpnessScriptableObject slashingSharpnessData = component.slashingSharpnessData;
					if ((Object)(object)slashingSharpnessData != (Object)null)
					{
						stringBuilder.Append("   sharpnessData '" + ((Object)slashingSharpnessData).name + "':" + Props(slashingSharpnessData) + "\n");
					}
					else
					{
						stringBuilder.Append("   sharpnessData: null\n");
					}
				}
				SlicerWeaponController component2 = ((Component)item).GetComponent<SlicerWeaponController>();
				if ((Object)(object)component2 != (Object)null)
				{
					stringBuilder.Append("   SlicerWeaponController:" + Props(component2, "Threshold|Power|ignore|check") + "\n");
				}
				if (!((Object)item).name.Contains("Wolverine") && !((Object)item).name.Contains("Lightsaber") && !((Object)item).name.Contains("Knife (Unsocketed"))
				{
					continue;
				}
				SortedSet<string> sortedSet = new SortedSet<string>();
				foreach (Component componentsInChild in ((Component)item).GetComponentsInChildren<Component>(true))
				{
					if ((Object)(object)componentsInChild != (Object)null)
					{
						sortedSet.Add(((MemberInfo)((Object)componentsInChild).GetIl2CppType()).Name);
					}
				}
				stringBuilder.Append("   components: " + string.Join(" ", sortedSet) + "\n");
				foreach (Collider componentsInChild2 in ((Component)item).GetComponentsInChildren<Collider>(true))
				{
					stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder4 = stringBuilder2;
					handler = new StringBuilder.AppendInterpolatedStringHandler(54, 6, stringBuilder2);
					handler.AppendLiteral("      collider '");
					handler.AppendFormatted(((Object)componentsInChild2).name);
					handler.AppendLiteral("' ");
					handler.AppendFormatted(((MemberInfo)((Object)componentsInChild2).GetIl2CppType()).Name);
					handler.AppendLiteral(" trigger=");
					handler.AppendFormatted(componentsInChild2.isTrigger);
					handler.AppendLiteral(" tag=");
					handler.AppendFormatted(((Component)componentsInChild2).tag);
					handler.AppendLiteral(" modifiable=");
					handler.AppendFormatted(componentsInChild2.hasModifiableContacts);
					handler.AppendLiteral(" enabled=");
					handler.AppendFormatted(componentsInChild2.enabled);
					handler.AppendLiteral("\n");
					stringBuilder4.Append(ref handler);
				}
				if (item.stabbingColliders != null)
				{
					foreach (Collider item2 in (Il2CppArrayBase<Collider>)(object)item.stabbingColliders)
					{
						if ((Object)(object)item2 != (Object)null)
						{
							stringBuilder2 = stringBuilder;
							StringBuilder stringBuilder5 = stringBuilder2;
							handler = new StringBuilder.AppendInterpolatedStringHandler(26, 1, stringBuilder2);
							handler.AppendLiteral("      stabbingCollider '");
							handler.AppendFormatted(((Object)item2).name);
							handler.AppendLiteral("'\n");
							stringBuilder5.Append(ref handler);
						}
					}
				}
				if (item.bladeColliders != null)
				{
					foreach (GameObject item3 in (Il2CppArrayBase<GameObject>)(object)item.bladeColliders)
					{
						if ((Object)(object)item3 != (Object)null)
						{
							stringBuilder2 = stringBuilder;
							StringBuilder stringBuilder6 = stringBuilder2;
							handler = new StringBuilder.AppendInterpolatedStringHandler(23, 1, stringBuilder2);
							handler.AppendLiteral("      bladeCollider '");
							handler.AppendFormatted(((Object)item3).name);
							handler.AppendLiteral("'\n");
							stringBuilder6.Append(ref handler);
						}
					}
				}
				if (item.slashLines != null)
				{
					foreach (SlashLineInfo item4 in (Il2CppArrayBase<SlashLineInfo>)(object)item.slashLines)
					{
						if (item4 != null)
						{
							stringBuilder2 = stringBuilder;
							StringBuilder stringBuilder7 = stringBuilder2;
							handler = new StringBuilder.AppendInterpolatedStringHandler(54, 5, stringBuilder2);
							handler.AppendLiteral("      slashLine bottom='");
							Transform slashBottom = item4.slashBottom;
							handler.AppendFormatted((slashBottom != null) ? ((Object)slashBottom).name : null);
							handler.AppendLiteral("' top='");
							Transform slashTop = item4.slashTop;
							handler.AppendFormatted((slashTop != null) ? ((Object)slashTop).name : null);
							handler.AppendLiteral("' fwd='");
							Transform slashForward = item4.slashForward;
							handler.AppendFormatted((slashForward != null) ? ((Object)slashForward).name : null);
							handler.AppendLiteral("' allowed=");
							handler.AppendFormatted((item4.allowedColliders != null) ? ((Il2CppArrayBase<Collider>)(object)item4.allowedColliders).Length : (-1));
							handler.AppendLiteral(" len=");
							handler.AppendFormatted(((Object)(object)item4.slashBottom != (Object)null && (Object)(object)item4.slashTop != (Object)null) ? Vector3.Distance(item4.slashBottom.position, item4.slashTop.position) : 0f, "F3");
							handler.AppendLiteral("\n");
							stringBuilder7.Append(ref handler);
						}
					}
				}
				Il2CppArrayBase<ConfigurableJoint> components = ((Component)item).GetComponents<ConfigurableJoint>();
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder8 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(36, 1, stringBuilder2);
				handler.AppendLiteral("      configurable joints on root: ");
				handler.AppendFormatted(components.Length);
				handler.AppendLiteral("\n");
				stringBuilder8.Append(ref handler);
				foreach (HVRStabber componentsInChild3 in ((Component)item).GetComponentsInChildren<HVRStabber>(true))
				{
					stringBuilder.Append("   HVRStabber on '" + ((Object)componentsInChild3).name + "':" + Props(componentsInChild3, "^(StabAnything|IgnoreVelocityCheck|ProjectionDistance|ProjectionAngle|IsDualStabber|CanRunThrough|ContactOffset|Length)$") + $" stabColliders={((componentsInChild3.StabbingColliders != null) ? ((Il2CppArrayBase<Collider>)(object)componentsInChild3.StabbingColliders).Length : (-1))} tip={(((Object)(object)componentsInChild3.Tip != (Object)null) ? ((Object)componentsInChild3.Tip).name : "-")} base={(((Object)(object)componentsInChild3.Base != (Object)null) ? ((Object)componentsInChild3.Base).name : "-")}\n");
					if ((Object)(object)componentsInChild3.Settings != (Object)null)
					{
						stringBuilder.Append("      Settings '" + ((Object)componentsInChild3.Settings).name + "':" + Props(componentsInChild3.Settings) + "\n");
					}
					if ((Object)(object)componentsInChild3.FallbackSettings != (Object)null)
					{
						stringBuilder.Append("      Fallback '" + ((Object)componentsInChild3.FallbackSettings).name + "':" + Props(componentsInChild3.FallbackSettings) + "\n");
					}
				}
			}
			int num = 0;
			foreach (HVRStabbable item5 in Resources.FindObjectsOfTypeAll<HVRStabbable>())
			{
				if (!((Object)(object)item5 == (Object)null) && !((Object)(object)item5.Settings == (Object)null) && num < 4)
				{
					stringBuilder.Append($"== HVRStabbable '{((Object)item5).name}' settings '{((Object)item5.Settings).name}':" + Props(item5.Settings) + "\n");
					num++;
				}
			}
			((MelonBase)this).LoggerInstance.Msg(stringBuilder.ToString());
		}

		private IEnumerator ScanLater(string scene)
		{
			float t = Time.time + 3f;
			while (Time.time < t)
			{
				yield return null;
			}
			if (Environment.GetEnvironmentVariable("WC_BUTTONSCAN") == "1")
			{
				try
				{
					ScanButtonEvents(scene);
				}
				catch (Exception ex)
				{
					((MelonBase)this).LoggerInstance.Warning("BUTTONSCAN: " + ex.Message);
				}
			}
			if (Environment.GetEnvironmentVariable("WC_SHARPDUMP") == "1")
			{
				try
				{
					DumpSharpness(scene);
				}
				catch (Exception ex2)
				{
					((MelonBase)this).LoggerInstance.Warning("SHARPDUMP: " + ex2.Message);
				}
				t = Time.time + 14f;
				while (Time.time < t)
				{
					yield return null;
				}
				try
				{
					DumpSharpness(scene + " (after claws)");
				}
				catch (Exception ex3)
				{
					((MelonBase)this).LoggerInstance.Warning("SHARPDUMP: " + ex3.Message);
				}
			}
		}

		public override void OnInitializeMelon()
		{
			if (Environment.GetEnvironmentVariable("WC_INPUTMAP") == "1")
			{
				try
				{
					DumpInputMap();
				}
				catch (Exception ex)
				{
					((MelonBase)this).LoggerInstance.Error("INPUTMAP: " + ex);
				}
			}
			_cat = MelonPreferences.CreateCategory("WolverineClaws");
			_clawLength = _cat.CreateEntry<float>("ClawLength", 0.3f, (string)null, "Blade length in metres", false, false, (ValueValidator)null, (string)null);
			_clawSpacing = _cat.CreateEntry<float>("ClawSpacing", 0.022f, (string)null, "Gap between the three claws (along the knuckles)", false, false, (ValueValidator)null, (string)null);
			_knuckleOffset = _cat.CreateEntry<float>("KnuckleOffset", 0.035f, (string)null, "How far in front of the grip the claws start", false, false, (ValueValidator)null, (string)null);
			_clawYaw = _cat.CreateEntry<float>("ClawYaw", 0f, (string)null, "Rotate claws around the grip axis (try 90/180/270 if they point the wrong way)", false, false, (ValueValidator)null, (string)null);
			_clawPitch = _cat.CreateEntry<float>("ClawPitch", 0f, (string)null, "Tilt claws up/down", false, false, (ValueValidator)null, (string)null);
			_clawSplay = _cat.CreateEntry<float>("ClawSplay", 2.5f, (string)null, "How much the outer claws fan out, in degrees", false, false, (ValueValidator)null, (string)null);
			_requireGrip = _cat.CreateEntry<bool>("RequireFist", false, (string)null, "(unused) old fist+trigger control", false, false, (ValueValidator)null, (string)null);
			_debugDump = _cat.CreateEntry<bool>("DebugDump", false, (string)null, "Log the built claw hierarchy", false, false, (ValueValidator)null, (string)null);
			_anchorToKnuckles = _cat.CreateEntry<bool>("AnchorToKnuckles", true, (string)null, "Place claws between the knuckles of your actual hand (any hand size). Off = fixed placement using KnuckleOffset/ClawYaw/ClawPitch", false, false, (ValueValidator)null, (string)null);
			_inputDebug = _cat.CreateEntry<bool>("InputDebug", false, (string)null, "Log each B/Y press (to troubleshoot controls)", false, false, (ValueValidator)null, (string)null);
			_clawButton = _cat.CreateEntry<string>("ClawButton", "Auto", (string)null, "Button that pops the claws: Auto (B/Y; Menu on Vive wands; touchpad click on original WMR), BY, AX, Menu, Trackpad, StickClick, FistTrigger (squeeze grip on an empty hand + pull trigger) or KeyboardOnly", false, false, (ValueValidator)null, (string)null);
			_keyLeft = _cat.CreateEntry<Key>("KeyLeft", (Key)100, (string)null, "Keyboard toggle for left claws (testing)", false, false, (ValueValidator)null, (string)null);
			_keyRight = _cat.CreateEntry<Key>("KeyRight", (Key)101, (string)null, "Keyboard toggle for right claws (testing)", false, false, (ValueValidator)null, (string)null);
			((MelonBase)this).LoggerInstance.Msg("SNIKT. Tap B (right hand) or Y (left hand) with an empty hand to pop the claws; tap again to retract. Vive wands: Menu; original WMR: touchpad click. ClawButton = " + _clawButton.Value);
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			if (_perfOnly)
			{
				return;
			}
			ClawVisuals.OnSceneChanged();
			try
			{
				ClawVisuals.GetMaterial(((MelonBase)this).LoggerInstance);
				ClawVisuals.ClawMesh(_clawLength.Value);
				ClawVisuals.ClawMesh(_clawLength.Value * 0.94f);
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Warning("Texture generation failed: " + ex.Message);
			}
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			ClawSever.ForgetColliders();
			_left.Hand = (_right.Hand = null);
			_left.Claws = (_right.Claws = null);
			_left.Grabbable = (_right.Grabbable = null);
			_left.Anchored = (_right.Anchored = false);
			_baseSo = null;
			_nextHandSearch = 0f;
			_autoAt = 0f;
			((MelonBase)this).LoggerInstance.Msg("Scene: " + sceneName);
			if (Environment.GetEnvironmentVariable("WC_BUTTONSCAN") == "1" || Environment.GetEnvironmentVariable("WC_SHARPDUMP") == "1")
			{
				MelonCoroutines.Start(ScanLater(sceneName));
			}
			if (_autoTest && !_scenesListed)
			{
				_scenesListed = true;
				int sceneCountInBuildSettings = SceneManager.sceneCountInBuildSettings;
				for (int i = 0; i < sceneCountInBuildSettings; i++)
				{
					((MelonBase)this).LoggerInstance.Msg($"  build scene {i}: {SceneUtility.GetScenePathByBuildIndex(i)}");
				}
				string environmentVariable = Environment.GetEnvironmentVariable("WC_SCENE");
				if (!string.IsNullOrEmpty(environmentVariable))
				{
					MelonCoroutines.Start(LoadLater(environmentVariable));
				}
			}
		}

		public override void OnFixedUpdate()
		{
			if (_perf)
			{
				_swFixed.Restart();
				_perfSteps++;
			}
			try
			{
				ClawSharpness.Tick();
			}
			catch (Exception ex)
			{
				if (_tickWarnings++ < 5)
				{
					((MelonBase)this).LoggerInstance.Warning("Pass-through tick: " + ex.Message);
				}
			}
			try
			{
				ClawSever.Tick();
			}
			catch (Exception ex2)
			{
				if (_tickWarnings++ < 5)
				{
					((MelonBase)this).LoggerInstance.Warning("Sever tick: " + ex2.Message);
				}
			}
			if (_perf)
			{
				_perfFixedMs += _swFixed.Elapsed.TotalMilliseconds;
			}
		}

		public override void OnUpdate()
		{
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: 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)
			if (!_perf)
			{
				UpdateCore();
				return;
			}
			Scene activeScene;
			if (_perfOnly)
			{
				float unscaledDeltaTime = Time.unscaledDeltaTime;
				_perfFrames++;
				_perfT += unscaledDeltaTime;
				_perfWorst = Math.Max(_perfWorst, (double)unscaledDeltaTime * 1000.0);
				if (_perfT >= 5f)
				{
					Instance loggerInstance = ((MelonBase)this).LoggerInstance;
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(26, 3);
					defaultInterpolatedStringHandler.AppendLiteral("PERFONLY ");
					activeScene = SceneManager.GetActiveScene();
					defaultInterpolatedStringHandler.AppendFormatted(((Scene)(ref activeScene)).name);
					defaultInterpolatedStringHandler.AppendLiteral(": ");
					defaultInterpolatedStringHandler.AppendFormatted((float)_perfFrames / _perfT, "F1");
					defaultInterpolatedStringHandler.AppendLiteral(" fps, worst ");
					defaultInterpolatedStringHandler.AppendFormatted(_perfWorst, "F1");
					defaultInterpolatedStringHandler.AppendLiteral(" ms");
					loggerInstance.Msg(defaultInterpolatedStringHandler.ToStringAndClear());
					_perfFrames = 0;
					_perfT = 0f;
					_perfWorst = 0.0;
				}
				return;
			}
			_sw.Restart();
			UpdateCore();
			_perfModMs += _sw.Elapsed.TotalMilliseconds;
			float unscaledDeltaTime2 = Time.unscaledDeltaTime;
			_perfFrames++;
			_perfT += unscaledDeltaTime2;
			_perfWorst = Math.Max(_perfWorst, (double)unscaledDeltaTime2 * 1000.0);
			if (_perfT >= 5f)
			{
				Instance loggerInstance2 = ((MelonBase)this).LoggerInstance;
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(69, 7);
				defaultInterpolatedStringHandler.AppendLiteral("PERF ");
				activeScene = SceneManager.GetActiveScene();
				defaultInterpolatedStringHandler.AppendFormatted(((Scene)(ref activeScene)).name);
				defaultInterpolatedStringHandler.AppendLiteral(": ");
				defaultInterpolatedStringHandler.AppendFormatted((float)_perfFrames / _perfT, "F1");
				defaultInterpolatedStringHandler.AppendLiteral(" fps, worst ");
				defaultInterpolatedStringHandler.AppendFormatted(_perfWorst, "F1");
				defaultInterpolatedStringHandler.AppendLiteral(" ms, mod ");
				defaultInterpolatedStringHandler.AppendFormatted(_perfModMs / (double)_perfFrames * 1000.0, "F1");
				defaultInterpolatedStringHandler.AppendLiteral(" us/frame + ");
				defaultInterpolatedStringHandler.AppendFormatted((_perfSteps > 0) ? (_perfFixedMs / (double)_perfSteps * 1000.0) : 0.0, "F1");
				defaultInterpolatedStringHandler.AppendLiteral(" us/physics step, claws L=");
				defaultInterpolatedStringHandler.AppendFormatted((Object)(object)_left.Claws != (Object)null);
				defaultInterpolatedStringHandler.AppendLiteral(" R=");
				defaultInterpolatedStringHandler.AppendFormatted((Object)(object)_right.Claws != (Object)null);
				loggerInstance2.Msg(defaultInterpolatedStringHandler.ToStringAndClear());
				_perfFrames = 0;
				_perfT = 0f;
				_perfWorst = 0.0;
				_perfModMs = 0.0;
				_perfFixedMs = 0.0;
				_perfSteps = 0;
			}
		}

		private void UpdateCore()
		{
			if (Time.time >= _nextHandSearch && ((Object)(object)_left.Hand == (Object)null || (Object)(object)_right.Hand == (Object)null))
			{
				_nextHandSearch = Time.time + 2f;
				FindHands();
			}
			Tick(_left);
			Tick(_right);
			if (!_autoTest || _autoDone || !((Object)(object)_left.Hand != (Object)null) || !((Object)(object)_right.Hand != (Object)null) || !((Object)(object)ModLoaderMelee.instanceOfThis != (Object)null))
			{
				return;
			}
			if (_autoAt == 0f)
			{
				_autoAt = Time.time + (float.TryParse(Environment.GetEnvironmentVariable("WC_POPDELAY"), out var result) ? result : 8f);
			}
			else if (Time.time >= _autoAt)
			{
				_autoDone = true;
				((MelonBase)this).LoggerInstance.Msg("AUTOTEST pop");
				if (!_photo && !_bloodTest && !_hitTest && !_swingTest && !_slashTest && !_driveTest)
				{
					Pop(_left);
				}
				Pop(_right);
			}
		}

		private IEnumerator LoadLater(string scene)
		{
			float until = Time.time + 6f;
			while (Time.time < until)
			{
				yield return null;
			}
			((MelonBase)this).LoggerInstance.Msg("AUTOTEST loading " + scene);
			SceneManager.LoadScene(scene);
		}

		private void FindHands()
		{
			foreach (HVRHandGrabber item in Object.FindObjectsByType<HVRHandGrabber>((FindObjectsSortMode)0))
			{
				if (!((Object)(object)item == (Object)null) && ((Component)item).gameObject.activeInHierarchy)
				{
					if (item.IsLeftHand)
					{
						_left.Hand = item;
					}
					else
					{
						_right.Hand = item;
					}
				}
			}
			if (_autoTest)
			{
				((MelonBase)this).LoggerInstance.Msg($"hands L={(Object)(object)_left.Hand != (Object)null} R={(Object)(object)_right.Hand != (Object)null} loader={(Object)(object)ModLoaderMelee.instanceOfThis != (Object)null}");
			}
		}

		private void Tick(Side s)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s.Claws != (Object)null && (Object)(object)s.Hand != (Object)null && (Object)(object)s.Grabbable != (Object)null && (Object)(object)((HVRGrabberBase)s.Hand).GrabbedTarget != (Object)(object)s.Grabbable)
			{
				Retract(s);
			}
			Keyboard current = Keyboard.current;
			bool flag = current != null && ((ButtonControl)current[s.Left ? _keyLeft.Value : _keyRight.Value]).wasPressedThisFrame;
			if ((Object)(object)s.Hand != (Object)null)
			{
				HVRController val = s.Hand.Controller;
				if ((Object)(object)val == (Object)null)
				{
					HVRInputManager instance = HVRInputManager.Instance;
					if ((Object)(object)instance != (Object)null)
					{
						val = (s.Left ? instance.LeftController : instance.RightController);
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					bool flag2 = ClawButtonDown(s, val);
					if (flag2 && !s.PrevTrigger)
					{
						flag = true;
						if (_inputDebug.Value)
						{
							((MelonBase)this).LoggerInstance.Msg(Name(s) + " " + ButtonLabel(s.Button, s.Left) + " pressed");
						}
					}
					s.PrevTrigger = flag2;
				}
			}
			if (flag)
			{
				if ((Object)(object)s.Claws != (Object)null)
				{
					Retract(s);
				}
				else
				{
					Pop(s);
				}
			}
		}

		private ClawBtn ButtonFor(HVRController c)
		{
			//IL_003d: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			string text = (_clawButton?.Value ?? "Auto").Trim();
			if (!text.Equals("Auto", StringComparison.OrdinalIgnoreCase) && Enum.TryParse<ClawBtn>(text, ignoreCase: true, out var result))
			{
				return result;
			}
			HVRControllerType controllerType = c.ControllerType;
			if ((int)controllerType != 2)
			{
				if ((int)controllerType == 3)
				{
					return ClawBtn.Menu;
				}
				return ClawBtn.BY;
			}
			return ClawBtn.Trackpad;
		}

		private static string ButtonLabel(int b, bool left)
		{
			return (ClawBtn)Math.Max(b, 0) switch
			{
				ClawBtn.BY => left ? "Y" : "B", 
				ClawBtn.AX => left ? "X" : "A", 
				ClawBtn.Menu => "Menu", 
				ClawBtn.Trackpad => "trackpad click", 
				ClawBtn.StickClick => "stick click", 
				ClawBtn.FistTrigger => "fist + trigger", 
				_ => "keyboard only", 
			};
		}

		private bool ClawButtonDown(Side s, HVRController c)
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			ClawBtn clawBtn = ButtonFor(c);
			if (clawBtn != (ClawBtn)s.Button)
			{
				s.Button = (int)clawBtn;
				((MelonBase)this).LoggerInstance.Msg($"{(s.Left ? "Left" : "Right")} controller: {c.ControllerType} -> claws on {ButtonLabel(s.Button, s.Left)}");
			}
			switch (clawBtn)
			{
			case ClawBtn.BY:
				if (!c.SecondaryButtonState.Active)
				{
					return c.SecondaryButton;
				}
				return true;
			case ClawBtn.AX:
				if (!c.PrimaryButtonState.Active)
				{
					return c.PrimaryButton;
				}
				return true;
			case ClawBtn.Menu:
				if (!c.MenuButtonState.Active)
				{
					return c.MenuButton;
				}
				return true;
			case ClawBtn.Trackpad:
				if (!c.TrackpadButtonState.Active)
				{
					return c.TrackPadClicked;
				}
				return true;
			case ClawBtn.StickClick:
				if (!c.JoystickButtonState.Active)
				{
					return c.JoystickClicked;
				}
				return true;
			case ClawBtn.FistTrigger:
			{
				HVRGrabbable grabbedTarget = ((HVRGrabberBase)s.Hand).GrabbedTarget;
				if (((Object)(object)grabbedTarget == (Object)null || ((Object)(object)s.Grabbable != (Object)null && (Object)(object)grabbedTarget == (Object)(object)s.Grabbable)) && (c.GripButtonState.Active || c.Grip > 0.7f))
				{
					if (!c.TriggerButtonState.Active)
					{
						return c.Trigger > 0.7f;
					}
					return true;
				}
				return false;
			}
			default:
				return false;
			}
		}

		private void Pop(Side s)
		{
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s.Hand == (Object)null)
			{
				FindHands();
				if ((Object)(object)s.Hand == (Object)null)
				{
					((MelonBase)this).LoggerInstance.Warning("No hand found yet");
					return;
				}
			}
			ModLoaderMelee instanceOfThis = ModLoaderMelee.instanceOfThis;
			if ((Object)(object)instanceOfThis == (Object)null)
			{
				((MelonBase)this).LoggerInstance.Warning("ModLoaderMelee not present in this scene");
				return;
			}
			if (((HVRGrabberBase)s.Hand).IsGrabbing && (Object)(object)((HVRGrabberBase)s.Hand).GrabbedTarget != (Object)null)
			{
				((MelonBase)this).LoggerInstance.Msg(Name(s) + " hand is holding " + ((Object)((HVRGrabberBase)s.Hand).GrabbedTarget).name + "; drop it first");
				return;
			}
			try
			{
				MeleeScriptableObject so;
				Il2CppReferenceArray<GameObject> grabObjs;
				Il2CppReferenceArray<Collider> stabCols;
				MeleeWeaponWrapper wrapper;
				GameObject val = BuildRaw(s, out so, out grabObjs, out stabCols, out wrapper);
				GameObject val2 = instanceOfThis.CreateMeleePrefab(val, so, grabObjs, stabCols, wrapper);
				GameObject val3 = val;
				HVRGrabbable val4 = val3.GetComponent<HVRGrabbable>();
				if ((Object)(object)val4 == (Object)null)
				{
					val4 = val3.GetComponentInChildren<HVRGrabbable>(true);
				}
				if (_debugDump.Value)
				{
					((MelonBase)this).LoggerInstance.Msg("Claw weapon:\n" + Dump(val3.transform, 0));
					if ((Object)(object)val2 != (Object)null)
					{
						((MelonBase)this).LoggerInstance.Msg("Socket returned: " + ((Object)val2).name + " parent=" + (Object.op_Implicit((Object)(object)val2.transform.parent) ? ((Object)val2.transform.parent).name : "-"));
					}
				}
				if ((Object)(object)val4 == (Object)null)
				{
					((MelonBase)this).LoggerInstance.Error("CreateMeleePrefab produced no HVRGrabbable");
					Object.Destroy((Object)(object)val3);
					if ((Object)(object)val2 != (Object)null)
					{
						Object.Destroy((Object)(object)val2);
					}
					return;
				}
				int value = ((instanceOfThis.loadedPrefabs != null) ? instanceOfThis.loadedPrefabs.Count : (-1));
				if (instanceOfThis.loadedPrefabs != null)
				{
					instanceOfThis.loadedPrefabs.Remove(val);
					if ((Object)(object)val2 != (Object)null)
					{
						instanceOfThis.loadedPrefabs.Remove(val2);
					}
				}
				if (ModLoaderMelee.unSocketedPrefabs != null)
				{
					ModLoaderMelee.unSocketedPrefabs.Remove(val);
					if ((Object)(object)val2 != (Object)null)
					{
						ModLoaderMelee.unSocketedPrefabs.Remove(val2);
					}
				}
				if (_autoTest)
				{
					((MelonBase)this).LoggerInstance.Msg($"loadedPrefabs {value} -> {((instanceOfThis.loadedPrefabs != null) ? instanceOfThis.loadedPrefabs.Count : (-1))}");
				}
				val4.StartingSocket = null;
				val4.LinkStartingSocket = false;
				val3.transform.SetParent((Transform)null, true);
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)val3)
				{
					Object.Destroy((Object)(object)val2);
				}
				((Object)val3).name = "WolverineClaws_" + Name(s);
				Transform transform = ((Component)s.Hand).transform;
				val3.transform.SetPositionAndRotation(transform.position, transform.rotation);
				if (_anchorToKnuckles.Value)
				{
					SetBladesVisible(val3, on: false);
				}
				val3.SetActive(true);
				val4.OverrideGrabTrigger = true;
				val4.GrabTrigger = (HVRGrabTrigger)2;
				val4.ForceGrabbable = false;
				foreach (HVRPosableGrabPoint componentsInChild in val3.GetComponentsInChildren<HVRPosableGrabPoint>(true))
				{
					componentsInChild.LineCanRotate = false;
					componentsInChild.LineInitialCanRotate = false;
					componentsInChild.LineFreeRotation = false;
					componentsInChild.LineCanReposition = false;
					componentsInChild.LineInitialCanReposition = false;
					componentsInChild.CanLineFlip = false;
				}
				s.Claws = val3;
				s.Grabbable = null;
				MelonCoroutines.Start(GrabSoon(s, val3, val4));
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error("Pop failed: " + ex);
			}
		}

		private IEnumerator GrabSoon(Side s, GameObject obj, HVRGrabbable grab)
		{
			yield return null;
			yield return null;
			if ((Object)(object)obj == (Object)null || (Object)(object)s.Claws != (Object)(object)obj)
			{
				yield break;
			}
			Transform transform = ((Component)s.Hand).transform;
			obj.transform.SetPositionAndRotation(transform.position, transform.rotation);
			bool flag = false;
			try
			{
				flag = ((HVRGrabberBase)s.Hand).TryGrab(grab, true);
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error("TryGrab: " + ex);
			}
			((MelonBase)this).LoggerInstance.Msg($"SNIKT ({Name(s)}) grab={flag}");
			if (flag)
			{
				s.Grabbable = grab;
				s.Anchored = false;
				Rigidbody component = obj.GetComponent<Rigidbody>();
				if ((Object)(object)component != (Object)null && !_noLock)
				{
					component.useGravity = false;
				}
				if (_anchorToKnuckles.Value)
				{
					MelonCoroutines.Start(SnapToKnuckles(s, obj));
				}
				MelonCoroutines.Start(SetupBloodSoon(obj));
				ClawSharpness.Apply(obj, ((MelonBase)this).LoggerInstance);
				ClawSever.Add(obj, ((MelonBase)this).LoggerInstance);
				MelonCoroutines.Start(ReapplySharpness(obj));
				try
				{
					HVRManager instance = HVRManager.Instance;
					if ((Object)(object)instance != (Object)null)
					{
						List<Collider> val = new List<Collider>();
						foreach (Collider componentsInChild in obj.GetComponentsInChildren<Collider>(true))
						{
							val.Add(componentsInChild);
						}
						instance.IgnorePlayerCollision(((Il2CppObjectBase)val).Cast<IEnumerable<Collider>>());
					}
					Transform root = ((Component)s.Hand).transform.root;
					Il2CppArrayBase<Collider> componentsInChildren = obj.GetComponentsInChildren<Collider>(true);
					foreach (Collider componentsInChild2 in ((Component)root).GetComponentsInChildren<Collider>(true))
					{
						foreach (Collider item in componentsInChildren)
						{
							if ((Object)(object)componentsInChild2 != (Object)null && (Object)(object)item != (Object)null)
							{
								Physics.IgnoreCollision(item, componentsInChild2, true);
							}
						}
					}
					Side side = (s.Left ? _right : _left);
					if ((Object)(object)side.Claws != (Object)null)
					{
						foreach (Collider componentsInChild3 in side.Claws.GetComponentsInChildren<Collider>(true))
						{
							foreach (Collider item2 in componentsInChildren)
							{
								if ((Object)(object)componentsInChild3 != (Object)null && (Object)(object)item2 != (Object)null)
								{
									Physics.IgnoreCollision(item2, componentsInChild3, true);
								}
							}
						}
					}
				}
				catch (Exception ex2)
				{
					((MelonBase)this).LoggerInstance.Warning("IgnorePlayerCollision: " + ex2.Message);
				}
				if (_photo)
				{
					float wait = Time.time + 1.2f;
					while (Time.time < wait)
					{
						yield return null;
					}
					if ((Object)(object)obj != (Object)null && !s.Left)
					{
						PhotoSet(s, obj);
					}
				}
				else if (_driveTest)
				{
					float wait = Time.time + 2f;
					while (Time.time < wait)
					{
						yield return null;
					}
					if ((Object)(object)obj != (Object)null && !s.Left)
					{
						yield return Environment.GetEnvironmentVariable("WC_DRIVETEST") switch
						{
							"2" => DriveTest2(s, obj), 
							"3" => RefWeaponTest(s, obj), 
							"4" => SwipeTest(s, obj), 
							"5" => IconShots(s, obj), 
							_ => DriveTest(s, obj), 
						};
					}
				}
				else if (_slashTest)
				{
					float wait = Time.time + 2f;
					while (Time.time < wait)
					{
						yield return null;
					}
					if ((Object)(object)obj != (Object)null && !s.Left)
					{
						yield return SlashTest(s, obj);
					}
				}
				else if (_swingTest)
				{
					float wait = Time.time + 1f;
					while (Time.time < wait)
					{
						yield return null;
					}
					if ((Object)(object)obj != (Object)null && !s.Left)
					{
						yield return SwingTest(s, obj);
					}
				}
				else if (_hitTest)
				{
					float wait = Time.time + 2f;
					while (Time.time < wait)
					{
						yield return null;
					}
					if ((Object)(object)obj != (Object)null && !s.Left)
					{
						yield return HitTest(s, obj);
					}
				}
				else if (_bloodTest)
				{
					float wait = Time.time + 1.2f;
					while (Time.time < wait)
					{
						yield return null;
					}
					if ((Object)(object)obj != (Object)null && !s.Left)
					{
						yield return BloodTest(s, obj);
					}
				}
				else
				{
					if (!_autoTest || s.AutoChecked)
					{
						yield break;
					}
					s.AutoChecked = true;
					float wait = Time.time + 2f;
					while (Time.time < wait)
					{
						yield return null;
					}
					if ((Object)(object)obj == (Object)null)
					{
						((MelonBase)this).LoggerInstance.Msg("AUTOTEST " + Name(s) + ": claws gone");
						yield break;
					}
					HVRGrabbable grabbedTarget = ((HVRGrabberBase)s.Hand).GrabbedTarget;
					((MelonBase)this).LoggerInstance.Msg($"AUTOTEST {Name(s)}: held={(((Object)(object)grabbedTarget != (Object)null) ? ((Object)grabbedTarget).name : "none")} dist={Vector3.Distance(obj.transform.position, ((Component)s.Hand).transform.position):F3} active={obj.activeInHierarchy}");
					Transform transform2 = ((Component)s.Hand).transform;
					Shot(transform2.position + transform2.up * 0.25f + transform2.right * (s.Left ? (-0.35f) : 0.35f) + transform2.forward * 0.1f, transform2.position + transform2.forward * 0.12f, ShotDir + "\\" + Name(s) + "_side.png");
					Shot(transform2.position + transform2.up * 0.5f + transform2.forward * 0.1f, transform2.position + transform2.forward * 0.12f, ShotDir + "\\" + Name(s) + "_top.png");
					Transform val2 = obj.transform.Find("Colliders/Blade1");
					if ((Object)(object)val2 != (Object)null)
					{
						float value = _clawLength.Value;
						Vector3 val3 = val2.position + val2.up * value * 0.55f;
						Shot(val3 + val2.right * 0.24f + val2.forward * 0.06f, val3, ShotDir + "\\" + Name(s) + "_close.png");
						Vector3 val4 = val2.position + val2.up * value * 0.88f;
						Shot(val4 + val2.right * 0.07f + val2.forward * 0.035f - val2.up * 0.02f, val4, ShotDir + "\\" + Name(s) + "_tip.png");
						if (MeasureKnuckles(s, out var a, log: false))
						{
							Vector3 centre = a.Centre;
							Vector3 at = centre + a.Dir * 0.06f;
							Shot(centre + a.Axis * 0.32f + a.Dir * 0.06f + a.Dorsal * 0.04f, at, ShotDir + "\\" + Name(s) + "_k_side.png", a.Dorsal);
							Shot(centre + a.Dorsal * 0.3f + a.Dir * 0.04f, at, ShotDir + "\\" + Name(s) + "_k_top.png", a.Dir);
							Shot(centre + a.Dir * 0.4f + a.Dorsal * 0.1f, centre, ShotDir + "\\" + Name(s) + "_k_front.png", a.Dorsal);
						}
					}
					wait = Time.time + 1f;
					while (Time.time < wait)
					{
						yield return null;
					}
					Retract(s);
					yield return null;
					((MelonBase)this).LoggerInstance.Msg($"AUTOTEST {Name(s)} after retract: claws={(Object)(object)obj != (Object)null} handGrabbing={((HVRGrabberBase)s.Hand).IsGrabbing}");
					wait = Time.time + 1f;
					while (Time.time < wait)
					{
						yield return null;
					}
					((MelonBase)this).LoggerInstance.Msg("AUTOTEST " + Name(s) + " re-pop");
					Pop(s);
				}
			}
			else
			{
				Retract(s);
			}
		}

		private static Transform BoneT(HVRPosableFinger f, int i)
		{
			if (f == null || f.Bones == null || f.Bones.Count <= i)
			{
				return null;
			}
			HVRPosableBone val = f.Bones[i];
			if (val == null)
			{
				return null;
			}
			return val.Transform;
		}

		private static Vector3? Knuckle(HVRPosableFinger f)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			Transform val = BoneT(f, 0);
			if ((Object)(object)val == (Object)null)
			{
				if (f == null || !((Object)(object)f.Root != (Object)null))
				{
					return null;
				}
				return f.Root.position;
			}
			if (((Object)val).name.ToLower().Contains("metacarpal"))
			{
				Transform val2 = BoneT(f, 1);
				if ((Object)(object)val2 != (Object)null)
				{
					val = val2;
				}
			}
			return val.position;
		}

		private bool MeasureKnuckles(Side s, out ClawAnchor a, bool log)
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknow