Decompiled source of LimbTear v1.0.0

Mods/LimbTear.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Il2Cpp;
using Il2CppActiveRagdoll;
using Il2CppHexabodyVR.PlayerController;
using Il2CppHurricaneVR.Framework.Core;
using Il2CppHurricaneVR.Framework.Core.Grabbers;
using Il2CppHurricaneVR.Framework.Core.Player;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using LimbTear;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "LimbTear", "1.0.0", "geom2543", null)]
[assembly: MelonGame("Kubunautilus", "BrutalistickVR")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("LimbTear")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6500443f73eb8753376512cf076649735b4ed368")]
[assembly: AssemblyProduct("LimbTear")]
[assembly: AssemblyTitle("LimbTear")]
[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 LimbTear
{
	public class Core : MelonMod
	{
		private class Grip
		{
			public IntPtr Limb;

			public string Name;

			public float Over;

			public float Max;
		}

		private MelonPreferences_Entry<bool> _enabled;

		private MelonPreferences_Entry<float> _force;

		private MelonPreferences_Entry<float> _hold;

		private MelonPreferences_Entry<float> _damage;

		private MelonPreferences_Entry<bool> _allowHead;

		private MelonPreferences_Entry<bool> _allowTorso;

		private MelonPreferences_Entry<bool> _verbose;

		private MelonPreferences_Entry<bool> _gore;

		private MelonPreferences_Entry<bool> _split;

		private MelonPreferences_Entry<float> _splitStretch;

		private MelonPreferences_Entry<float> _splitHold;

		private IntPtr _splitPart;

		private float _splitBase;

		private float _splitOver;

		private float _splitMax;

		private MelonPreferences_Entry<int> _bleedSources;

		private readonly Dictionary<IntPtr, Grip> _grips = new Dictionary<IntPtr, Grip>();

		private readonly List<ConfigurableJoint> _torn = new List<ConfigurableJoint>();

		private HexaBodyPlayer4 _body;

		private Transform _rig;

		private static readonly JointDrive Zero;

		public override void OnInitializeMelon()
		{
			MelonPreferences_Category val = MelonPreferences.CreateCategory("LimbTear");
			_enabled = val.CreateEntry<bool>("Enabled", true, "Enabled", (string)null, false, false, (ValueValidator)null, (string)null);
			_force = val.CreateEntry<float>("TearForce", 1800f, "Tear force (N)", "Pull on a body part joint needed to rip it off. Lower = easier", false, false, (ValueValidator)null, (string)null);
			_hold = val.CreateEntry<float>("HoldTime", 0.2f, "Hold time (s)", "How long the pull must stay above the tear force", false, false, (ValueValidator)null, (string)null);
			_damage = val.CreateEntry<float>("DismemberDamage", 60f, "Damage on tear", (string)null, false, false, (ValueValidator)null, (string)null);
			_allowHead = val.CreateEntry<bool>("AllowHead", true, "Heads can be ripped off", (string)null, false, false, (ValueValidator)null, (string)null);
			_allowTorso = val.CreateEntry<bool>("TorsoCanTear", true, "Torso can be ripped apart (chest, neck, pelvis)", (string)null, false, false, (ValueValidator)null, (string)null);
			_gore = val.CreateEntry<bool>("Gore", true, "Blood, splatter and sound on tear", (string)null, false, false, (ValueValidator)null, (string)null);
			_bleedSources = val.CreateEntry<int>("BleedSources", 3, "Bleeding spots per wound side", (string)null, false, false, (ValueValidator)null, (string)null);
			_split = val.CreateEntry<bool>("SplitWithTwoHands", true, "Rip one body part in half with two hands", (string)null, false, false, (ValueValidator)null, (string)null);
			_splitStretch = val.CreateEntry<float>("SplitPull", 0.18f, "Split pull (m)", "How far apart your controllers must go past the grab (both hands on one part)", false, false, (ValueValidator)null, (string)null);
			_splitHold = val.CreateEntry<float>("SplitHoldTime", 0.25f, "Split hold time (s)", (string)null, false, false, (ValueValidator)null, (string)null);
			_verbose = val.CreateEntry<bool>("Verbose", true, "Log the strongest pull of every grab (to tune TearForce)", (string)null, false, false, (ValueValidator)null, (string)null);
			((MelonBase)this).LoggerInstance.Msg("Loaded. Grab an NPC limb and pull hard to rip it off.");
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			_grips.Clear();
			_torn.Clear();
			_body = null;
		}

		private bool FindBody()
		{
			if ((Object)(object)_body != (Object)null && !((Il2CppObjectBase)_body).WasCollected && Object.op_Implicit((Object)(object)_body))
			{
				return true;
			}
			_body = Object.FindObjectOfType<HexaBodyPlayer4>();
			if ((Object)(object)_body == (Object)null)
			{
				return false;
			}
			_rig = (((Object)(object)((Component)_body).transform.parent != (Object)null) ? ((Component)_body).transform.parent : ((Component)_body).transform);
			return true;
		}

		public override void OnFixedUpdate()
		{
			for (int num = _torn.Count - 1; num >= 0; num--)
			{
				ConfigurableJoint val = _torn[num];
				if ((Object)(object)val == (Object)null || ((Il2CppObjectBase)val).WasCollected || !Object.op_Implicit((Object)(object)val))
				{
					_torn.RemoveAt(num);
				}
				else
				{
					Limp(val);
				}
			}
		}

		public override void OnUpdate()
		{
			if (!_enabled.Value || !FindBody())
			{
				return;
			}
			foreach (HVRHexaBodyHands componentsInChild in ((Component)_rig).GetComponentsInChildren<HVRHexaBodyHands>(false))
			{
				try
				{
					UpdateHand(componentsInChild);
				}
				catch (Exception ex)
				{
					((MelonBase)this).LoggerInstance.Warning("LimbTear: " + ex.Message);
				}
			}
			try
			{
				UpdateSplit();
			}
			catch (Exception ex2)
			{
				((MelonBase)this).LoggerInstance.Warning("Split: " + ex2.Message);
			}
		}

		private static Rigidbody HeldPart(HVRHexaBodyHands h, out StickHealth npc)
		{
			npc = null;
			HVRHandGrabber val = (((Object)(object)h != (Object)null) ? h.Grabber : null);
			HVRGrabbable val2 = (((Object)(object)val != (Object)null && ((HVRGrabberBase)val).IsGrabbing) ? ((HVRGrabberBase)val).GrabbedTarget : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			npc = ((Component)val2).GetComponentInParent<StickHealth>();
			if ((Object)(object)npc == (Object)null)
			{
				return null;
			}
			if (!((Object)(object)val2.Rigidbody != (Object)null))
			{
				return ((Component)val2).GetComponentInParent<Rigidbody>();
			}
			return val2.Rigidbody;
		}

		private void UpdateSplit()
		{
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: 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_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			if (!_split.Value)
			{
				return;
			}
			HVRHexaBodyHands val = null;
			HVRHexaBodyHands val2 = null;
			foreach (HVRHexaBodyHands componentsInChild in ((Component)_rig).GetComponentsInChildren<HVRHexaBodyHands>(false))
			{
				if (!((Object)(object)componentsInChild == (Object)null) && !((Object)(object)componentsInChild.Grabber == (Object)null))
				{
					if (componentsInChild.Grabber.IsLeftHand)
					{
						val = componentsInChild;
					}
					else
					{
						val2 = componentsInChild;
					}
				}
			}
			StickHealth npc;
			Rigidbody val3 = HeldPart(val, out npc);
			StickHealth npc2;
			Rigidbody val4 = HeldPart(val2, out npc2);
			if ((Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || ((Il2CppObjectBase)val3).Pointer != ((Il2CppObjectBase)val4).Pointer || (Object)(object)_body.LeftController == (Object)null || (Object)(object)_body.RightController == (Object)null)
			{
				if (_splitPart != IntPtr.Zero && _verbose.Value && _splitMax > 0.01f)
				{
					((MelonBase)this).LoggerInstance.Msg($"Let go (two hands): strongest pull-apart {_splitMax:F2} m (split at {_splitStretch.Value:F2} m)");
				}
				_splitPart = IntPtr.Zero;
				return;
			}
			float num = Mathf.Max(0.01f, _rig.lossyScale.x);
			Vector3 position = ((Component)val).transform.position;
			Vector3 position2 = ((Component)val2).transform.position;
			float num2 = (Vector3.Distance(_body.LeftController.position, _body.RightController.position) - Vector3.Distance(position, position2)) / num;
			if (_splitPart != ((Il2CppObjectBase)val3).Pointer)
			{
				_splitPart = ((Il2CppObjectBase)val3).Pointer;
				_splitBase = num2;
				_splitOver = 0f;
				_splitMax = 0f;
				return;
			}
			float num3 = num2 - _splitBase;
			_splitMax = Mathf.Max(_splitMax, num3);
			_splitOver = ((num3 >= _splitStretch.Value) ? (_splitOver + Time.deltaTime) : Mathf.Max(0f, _splitOver - Time.deltaTime));
			if (!(_splitOver < _splitHold.Value))
			{
				_splitPart = IntPtr.Zero;
				Split(npc, val3, val, val2, position, position2, num3);
			}
		}

		private void Split(StickHealth npc, Rigidbody part, HVRHexaBodyHands l, HVRHexaBodyHands r, Vector3 hl, Vector3 hr, float pull)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			ColliderBridge component = ((Component)part).GetComponent<ColliderBridge>();
			if ((Object)(object)component == (Object)null)
			{
				((MelonBase)this).LoggerInstance.Warning("'" + ((Object)part).name + "' can't be split (no ColliderBridge)");
				return;
			}
			Vector3 val = hr - hl;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			Vector3 val2 = (hl + hr) * 0.5f;
			Plane val3 = default(Plane);
			((Plane)(ref val3))..ctor(normalized, val2);
			if (_gore.Value)
			{
				try
				{
					GoreFx(npc, part, val2, normalized);
					GoreFx(npc, part, val2, -normalized);
				}
				catch
				{
				}
			}
			Rigidbody rigidBody = ((HexaHandsBase)l).RigidBody;
			Il2CppArrayBase<Collider> val4 = (((Object)(object)rigidBody != (Object)null) ? ((Component)rigidBody).GetComponentsInChildren<Collider>() : null);
			Il2CppReferenceArray<Collider> val5 = new Il2CppReferenceArray<Collider>((long)(val4?.Length ?? 0));
			int num = 0;
			while (val4 != null && num < val4.Length)
			{
				((Il2CppArrayBase<Collider>)(object)val5)[num] = val4[num];
				num++;
			}
			component.SliceColliderBridge(val3, val2, normalized * 2f, rigidBody, val5, ((HexaHandsBase)r).RigidBody, 0.3f);
			try
			{
				npc.DismemberDetected(_damage.Value, (DamageType)1, component.damageRegion, component);
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Warning("DismemberDetected: " + ex.Message);
			}
			((MelonBase)this).LoggerInstance.Msg($"Ripped '{((Object)part).name}' in half (pulled apart {pull:F2} m)");
		}

		private void UpdateHand(HVRHexaBodyHands h)
		{
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)h == (Object)null)
			{
				return;
			}
			HVRHandGrabber grabber = h.Grabber;
			HVRGrabbable val = (((Object)(object)grabber != (Object)null && ((HVRGrabberBase)grabber).IsGrabbing) ? ((HVRGrabberBase)grabber).GrabbedTarget : null);
			Rigidbody val2 = null;
			StickHealth val3 = null;
			if ((Object)(object)val != (Object)null)
			{
				val2 = (((Object)(object)val.Rigidbody != (Object)null) ? val.Rigidbody : ((Component)val).GetComponentInParent<Rigidbody>());
				val3 = ((Component)val).GetComponentInParent<StickHealth>();
			}
			_grips.TryGetValue(((Il2CppObjectBase)h).Pointer, out var value);
			if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
			{
				if (value != null)
				{
					LogGrip(value);
					_grips.Remove(((Il2CppObjectBase)h).Pointer);
				}
				return;
			}
			if (value == null || value.Limb != ((Il2CppObjectBase)val2).Pointer)
			{
				if (value != null)
				{
					LogGrip(value);
				}
				value = new Grip
				{
					Limb = ((Il2CppObjectBase)val2).Pointer,
					Name = ((Object)val2).name
				};
				_grips[((Il2CppObjectBase)h).Pointer] = value;
			}
			if (!Allowed(((Object)val2).name))
			{
				return;
			}
			List<ConfigurableJoint> list = FindCuts(val3, val2);
			if (list.Count == 0)
			{
				return;
			}
			float num = 0f;
			foreach (ConfigurableJoint item in list)
			{
				float num2 = num;
				Vector3 currentForce = ((Joint)item).currentForce;
				num = Mathf.Max(num2, ((Vector3)(ref currentForce)).magnitude);
			}
			value.Max = Mathf.Max(value.Max, num);
			value.Over = ((num >= _force.Value) ? (value.Over + Time.deltaTime) : Mathf.Max(0f, value.Over - Time.deltaTime));
			if (value.Over >= _hold.Value)
			{
				Tear(val3, val2, list, num);
				value.Over = 0f;
			}
		}

		private bool Allowed(string n)
		{
			if (n.StartsWith("Head") || n == "Jaw")
			{
				return _allowHead.Value;
			}
			if (n.Contains("Chest") || n.Contains("Neck") || n.Contains("Spine") || n.Contains("Pelvis"))
			{
				return _allowTorso.Value;
			}
			return true;
		}

		private static List<ConfigurableJoint> FindCuts(StickHealth npc, Rigidbody limb)
		{
			List<ConfigurableJoint> list = new List<ConfigurableJoint>();
			Il2CppArrayBase<ConfigurableJoint> componentsInChildren = ((Component)npc).GetComponentsInChildren<ConfigurableJoint>(false);
			Rigidbody val = null;
			List<(IntPtr, IntPtr, ConfigurableJoint)> list2 = new List<(IntPtr, IntPtr, ConfigurableJoint)>();
			foreach (ConfigurableJoint item in componentsInChildren)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				Rigidbody component = ((Component)item).GetComponent<Rigidbody>();
				Rigidbody connectedBody = ((Joint)item).connectedBody;
				if (!((Object)(object)component == (Object)null) && !((Object)(object)connectedBody == (Object)null) && !IsFree(item))
				{
					list2.Add((((Il2CppObjectBase)component).Pointer, ((Il2CppObjectBase)connectedBody).Pointer, item));
					if ((Object)(object)val == (Object)null && ((Object)component).name == "Pelvis")
					{
						val = component;
					}
					if ((Object)(object)val == (Object)null && ((Object)connectedBody).name == "Pelvis")
					{
						val = connectedBody;
					}
				}
			}
			HashSet<IntPtr> hashSet = Reach(list2, ((Il2CppObjectBase)limb).Pointer, IntPtr.Zero);
			IntPtr intPtr = IntPtr.Zero;
			if ((Object)(object)val != (Object)null && ((Il2CppObjectBase)val).Pointer != ((Il2CppObjectBase)limb).Pointer && hashSet.Contains(((Il2CppObjectBase)val).Pointer))
			{
				intPtr = ((Il2CppObjectBase)val).Pointer;
			}
			else
			{
				float num = 0f;
				foreach (var item2 in list2)
				{
					IntPtr intPtr2;
					if (!(item2.Item1 == ((Il2CppObjectBase)limb).Pointer))
					{
						if (item2.Item2 == ((Il2CppObjectBase)limb).Pointer)
						{
							(intPtr2, _, _) = item2;
						}
						else
						{
							intPtr2 = IntPtr.Zero;
						}
					}
					else
					{
						intPtr2 = item2.Item2;
					}
					IntPtr intPtr3 = intPtr2;
					if (!(intPtr3 == IntPtr.Zero))
					{
						float num2 = (float)Reach(list2, intPtr3, ((Il2CppObjectBase)limb).Pointer).Count + ((item2.Item1 == ((Il2CppObjectBase)limb).Pointer) ? 0.5f : 0f);
						if (num2 > num)
						{
							num = num2;
							intPtr = intPtr3;
						}
					}
				}
			}
			if (intPtr == IntPtr.Zero)
			{
				return list;
			}
			HashSet<IntPtr> hashSet2 = Reach(list2, intPtr, ((Il2CppObjectBase)limb).Pointer);
			foreach (var item3 in list2)
			{
				if (item3.Item1 == ((Il2CppObjectBase)limb).Pointer && hashSet2.Contains(item3.Item2))
				{
					list.Add(item3.Item3);
				}
				else if (item3.Item2 == ((Il2CppObjectBase)limb).Pointer && hashSet2.Contains(item3.Item1))
				{
					list.Add(item3.Item3);
				}
			}
			return list;
		}

		private static HashSet<IntPtr> Reach(List<(IntPtr a, IntPtr b, ConfigurableJoint j)> edges, IntPtr start, IntPtr skip)
		{
			HashSet<IntPtr> hashSet = new HashSet<IntPtr> { start };
			Queue<IntPtr> queue = new Queue<IntPtr>();
			queue.Enqueue(start);
			while (queue.Count > 0)
			{
				IntPtr intPtr = queue.Dequeue();
				foreach (var edge in edges)
				{
					IntPtr intPtr2;
					if (!(edge.a == intPtr))
					{
						if (edge.b == intPtr)
						{
							(intPtr2, _, _) = edge;
						}
						else
						{
							intPtr2 = IntPtr.Zero;
						}
					}
					else
					{
						intPtr2 = edge.b;
					}
					IntPtr intPtr3 = intPtr2;
					if (!(intPtr3 == IntPtr.Zero) && !(intPtr3 == skip) && !hashSet.Contains(intPtr3))
					{
						hashSet.Add(intPtr3);
						queue.Enqueue(intPtr3);
					}
				}
			}
			return hashSet;
		}

		private void Tear(StickHealth npc, Rigidbody limb, List<ConfigurableJoint> cuts, float force)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
			Vector3 worldCenterOfMass = limb.worldCenterOfMass;
			foreach (ConfigurableJoint cut in cuts)
			{
				worldCenterOfMass = ((Component)cut).transform.TransformPoint(((Joint)cut).anchor);
				Rigidbody val = ((((Il2CppObjectBase)((Component)cut).GetComponent<Rigidbody>()).Pointer == ((Il2CppObjectBase)limb).Pointer) ? ((Joint)cut).connectedBody : ((Component)cut).GetComponent<Rigidbody>());
				Vector3 val2 = limb.worldCenterOfMass - worldCenterOfMass;
				Vector3 normalized = ((Vector3)(ref val2)).normalized;
				ConfigurableJointMotion val3 = (ConfigurableJointMotion)2;
				cut.zMotion = (ConfigurableJointMotion)2;
				ConfigurableJointMotion xMotion = (cut.yMotion = val3);
				cut.xMotion = xMotion;
				val3 = (ConfigurableJointMotion)2;
				cut.angularZMotion = (ConfigurableJointMotion)2;
				xMotion = (cut.angularYMotion = val3);
				cut.angularXMotion = xMotion;
				cut.projectionMode = (JointProjectionMode)0;
				Limp(cut);
				_torn.Add(cut);
				StopDriving(((Component)cut).gameObject);
				if (_gore.Value)
				{
					Gore(npc, limb, worldCenterOfMass, normalized);
					if ((Object)(object)val != (Object)null)
					{
						Gore(npc, val, worldCenterOfMass, -normalized);
					}
				}
			}
			try
			{
				ColliderBridge component = ((Component)limb).GetComponent<ColliderBridge>();
				npc.DismemberDetected(_damage.Value, (DamageType)1, ((Object)(object)component != (Object)null) ? component.damageRegion : ((Object)limb).name, component);
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Warning("DismemberDetected: " + ex.Message);
			}
			((MelonBase)this).LoggerInstance.Msg($"Ripped off '{((Object)limb).name}' ({force:F0} N, {cuts.Count} joint{((cuts.Count == 1) ? "" : "s")})");
		}

		private void GoreFx(StickHealth npc, Rigidbody part, Vector3 pos, Vector3 dir)
		{
			//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)
			Gore(npc, part, pos, dir, bleedSources: false);
		}

		private void Gore(StickHealth npc, Rigidbody part, Vector3 pos, Vector3 dir, bool bleedSources = true)
		{
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			ColliderBridge val = null;
			try
			{
				val = ((Component)part).GetComponent<ColliderBridge>();
			}
			catch
			{
			}
			try
			{
				GameObject val2 = (((Object)(object)val != (Object)null) ? val.bleedSourcePrefab : null);
				if ((Object)(object)val2 == (Object)null && (Object)(object)DefaultReferences.Instance != (Object)null)
				{
					val2 = DefaultReferences.Instance.bleedSourcePrefab;
				}
				if ((Object)(object)val2 != (Object)null && bleedSources)
				{
					for (int i = 0; i < Mathf.Max(0, _bleedSources.Value); i++)
					{
						Vector3 val3 = pos + Random.insideUnitSphere * 0.03f;
						Object.Instantiate<GameObject>(val2, val3, Quaternion.LookRotation(dir), ((Component)part).transform).SetActive(true);
					}
				}
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Warning("Bleed source: " + ex.Message);
			}
			try
			{
				foreach (ParticleSystem componentsInChild in ((Component)part).GetComponentsInChildren<ParticleSystem>(true))
				{
					if (!((Object)(object)componentsInChild == (Object)null))
					{
						string name = ((Object)componentsInChild).name;
						if (name.Contains("Confetti") || name.Contains("Splash"))
						{
							Splash(componentsInChild, pos, dir);
						}
					}
				}
				foreach (ParticleSystem componentsInChild2 in ((Component)npc).GetComponentsInChildren<ParticleSystem>(true))
				{
					if ((Object)(object)componentsInChild2 != (Object)null && ((Object)componentsInChild2).name == "BloodSmokePuff")
					{
						Splash(componentsInChild2, pos, dir);
						break;
					}
				}
			}
			catch (Exception ex2)
			{
				((MelonBase)this).LoggerInstance.Warning("Blood particles: " + ex2.Message);
			}
			try
			{
				if ((Object)(object)val != (Object)null)
				{
					val.PlaySlashSound(pos, 1f);
				}
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)val != (Object)null && val.hasArtery)
				{
					val.ArteryCut(pos, dir);
				}
			}
			catch
			{
			}
		}

		private static void Splash(ParticleSystem ps, Vector3 pos, Vector3 dir)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Transform transform = ((Component)ps).transform;
			transform.position = pos;
			transform.rotation = Quaternion.FromToRotation(transform.up, dir) * transform.rotation;
			if (!((Component)ps).gameObject.activeSelf)
			{
				((Component)ps).gameObject.SetActive(true);
			}
			ps.Play(true);
		}

		private static void StopDriving(GameObject go)
		{
			foreach (MonoBehaviour component in go.GetComponents<MonoBehaviour>())
			{
				if (!((Object)(object)component == (Object)null) && ((Object)(object)((Il2CppObjectBase)component).TryCast<ActRagJoint>() != (Object)null || (Object)(object)((Il2CppObjectBase)component).TryCast<ActRagHipJoint>() != (Object)null || (Object)(object)((Il2CppObjectBase)component).TryCast<StickJointBreaker>() != (Object)null))
				{
					((Behaviour)component).enabled = false;
				}
			}
		}

		private static bool IsFree(ConfigurableJoint j)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			if ((int)j.xMotion == 2 && (int)j.yMotion == 2 && (int)j.zMotion == 2)
			{
				return (int)j.angularXMotion == 2;
			}
			return false;
		}

		private static void Limp(ConfigurableJoint j)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			j.xDrive = Zero;
			j.yDrive = Zero;
			j.zDrive = Zero;
			j.angularXDrive = Zero;
			j.angularYZDrive = Zero;
			j.slerpDrive = Zero;
		}

		private void LogGrip(Grip g)
		{
			if (_verbose.Value && g.Max > 1f)
			{
				((MelonBase)this).LoggerInstance.Msg($"Let go of '{g.Name}': strongest pull {g.Max:F0} N (tear at {_force.Value:F0} N)");
			}
		}

		static Core()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			JointDrive zero = default(JointDrive);
			((JointDrive)(ref zero)).positionSpring = 0f;
			((JointDrive)(ref zero)).positionDamper = 0f;
			((JointDrive)(ref zero)).maximumForce = 0f;
			Zero = zero;
		}
	}
}