Decompiled source of Grabdoll v1.0.0

Mods/StandaloneRagdoll.dll

Decompiled a month ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSystem.Collections.Generic;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using StandaloneRagdoll;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(RagdollMod), "Standalone Grabdoll", "1.2.0", "DOOBER", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("StandaloneRagdoll")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("StandaloneRagdoll")]
[assembly: AssemblyTitle("StandaloneRagdoll")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 StandaloneRagdoll
{
	public enum RagdollMode
	{
		LIMP,
		ARM_CONTROL
	}
	public class RagdollMod : MelonMod
	{
		private static MelonPreferences_Category _prefCategory;

		private static MelonPreferences_Entry<bool> _prefEnabled;

		private static MelonPreferences_Entry<bool> _prefGrabEnabled;

		private static MelonPreferences_Entry<int> _prefMode;

		private static MelonPreferences_Entry<bool> _prefTantrumMode;

		public override void OnInitializeMelon()
		{
			_prefCategory = MelonPreferences.CreateCategory("Grabdoll");
			_prefEnabled = _prefCategory.CreateEntry<bool>("Enabled", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_prefGrabEnabled = _prefCategory.CreateEntry<bool>("GrabEnabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_prefMode = _prefCategory.CreateEntry<int>("Mode", 0, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_prefTantrumMode = _prefCategory.CreateEntry<bool>("TantrumMode", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			RagdollController.Enabled = _prefEnabled.Value;
			RagdollController.GrabEnabled = _prefGrabEnabled.Value;
			RagdollController.Mode = (RagdollMode)_prefMode.Value;
			RagdollController.TantrumMode = _prefTantrumMode.Value;
			RagdollController.Initialize();
			((MelonBase)this).LoggerInstance.Msg("Standalone Grabdoll mod loaded");
		}

		public override void OnLateInitializeMelon()
		{
			BuildMenu();
		}

		public override void OnUpdate()
		{
			RagdollController.Update();
		}

		public override void OnApplicationQuit()
		{
			SavePreferences();
		}

		public static void SavePreferences()
		{
			if (_prefCategory != null)
			{
				_prefEnabled.Value = RagdollController.Enabled;
				_prefGrabEnabled.Value = RagdollController.GrabEnabled;
				_prefMode.Value = (int)RagdollController.Mode;
				_prefTantrumMode.Value = RagdollController.TantrumMode;
				_prefCategory.SaveToFile(false);
			}
		}

		private void BuildMenu()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			Page val = Page.Root.CreatePage("Grabdoll", Color.red, 0, true);
			val.CreateBool("Enabled", Color.white, RagdollController.Enabled, (Action<bool>)delegate(bool value)
			{
				RagdollController.Enabled = value;
				SavePreferences();
			});
			val.CreateBool("Grab Ragdoll", Color.yellow, RagdollController.GrabEnabled, (Action<bool>)delegate(bool value)
			{
				RagdollController.GrabEnabled = value;
				SavePreferences();
			});
			val.CreateEnum("Mode", Color.cyan, (Enum)RagdollController.Mode, (Action<Enum>)delegate(Enum value)
			{
				RagdollController.Mode = (RagdollMode)(object)value;
				SavePreferences();
			});
			val.CreateBool("Tantrum Mode", Color.red, RagdollController.TantrumMode, (Action<bool>)delegate(bool value)
			{
				RagdollController.TantrumMode = value;
				SavePreferences();
			});
		}
	}
	public static class RagdollController
	{
		private static bool _enabled = false;

		private static RagdollMode _mode = RagdollMode.LIMP;

		private static bool _tantrumMode = false;

		private static bool _grabEnabled = true;

		private static bool _sceneLoaded = false;

		private static float _nextRagdollTime = 0f;

		private static float _ragdollCooldownUntil = 0f;

		private const float COOLDOWN = 2f;

		private static Grip[] _cachedRigGrips = null;

		private static float _lastGripCacheTime = 0f;

		private const float GRIP_CACHE_INTERVAL = 2f;

		public static bool Enabled
		{
			get
			{
				return _enabled;
			}
			set
			{
				_enabled = value;
				MelonLogger.Msg("Ragdoll Controller " + (value ? "ENABLED" : "DISABLED"));
			}
		}

		public static bool GrabEnabled
		{
			get
			{
				return _grabEnabled;
			}
			set
			{
				_grabEnabled = value;
			}
		}

		public static RagdollMode Mode
		{
			get
			{
				return _mode;
			}
			set
			{
				_mode = value;
				MelonLogger.Msg($"Ragdoll Mode: {value}");
			}
		}

		public static bool TantrumMode
		{
			get
			{
				return _tantrumMode;
			}
			set
			{
				_tantrumMode = value;
				MelonLogger.Msg("Tantrum Mode: " + (value ? "ON (basic ragdoll)" : "OFF (LIMP/ARM_CONTROL)"));
			}
		}

		public static void Initialize()
		{
			Hooking.OnLevelLoaded += delegate
			{
				OnSceneLoaded();
			};
			Hooking.OnPlayerDeath += OnPlayerDeathHook;
			Hooking.OnPlayerResurrected += OnPlayerResurrectedHook;
			MelonLogger.Msg("RagdollController initialized");
		}

		private static void OnSceneLoaded()
		{
			_sceneLoaded = true;
			_cachedRigGrips = null;
			_lastGripCacheTime = 0f;
			_nextRagdollTime = 0f;
		}

		public static void Update()
		{
			if (!_enabled || !_sceneLoaded || Time.time < _ragdollCooldownUntil)
			{
				return;
			}
			try
			{
				PhysicsRig physicsRig = Player.PhysicsRig;
				if (!((Object)(object)physicsRig == (Object)null))
				{
					RigManager rigManager = Player.RigManager;
					if (!((Object)(object)rigManager == (Object)null) && !physicsRig.torso.shutdown && physicsRig.ballLocoEnabled && !(Time.time < _nextRagdollTime) && _grabEnabled)
					{
						CheckGrabRagdoll(rigManager, physicsRig);
					}
				}
			}
			catch
			{
			}
		}

		private static void CheckGrabRagdoll(RigManager rigManager, PhysicsRig physRig)
		{
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PhysTorso torso = physRig.torso;
				if ((Object)(object)torso == (Object)null)
				{
					return;
				}
				float rigMass = GetRigMass(rigManager);
				RigManager externalGrabber = GetExternalGrabber(torso.gHead, rigManager);
				RigManager externalGrabber2 = GetExternalGrabber((Grip)(object)torso.gNeck, rigManager);
				if ((Object)(object)externalGrabber != (Object)null && GetRigMass(externalGrabber) > rigMass * 0.9f)
				{
					TriggerRagdoll(rigManager, "Head Grab", dropItems: false);
					return;
				}
				if ((Object)(object)externalGrabber2 != (Object)null && GetRigMass(externalGrabber2) > rigMass * 0.9f)
				{
					TriggerRagdoll(rigManager, "Neck Grab", dropItems: false);
					return;
				}
				RefreshGripCache(rigManager);
				RigManager val = null;
				RigManager val2 = null;
				if (_cachedRigGrips != null)
				{
					Transform val3 = (((Object)(object)physRig.leftHand != (Object)null) ? ((Component)physRig.leftHand).transform : null);
					Transform val4 = (((Object)(object)physRig.rightHand != (Object)null) ? ((Component)physRig.rightHand).transform : null);
					Transform transform = ((Component)rigManager).transform;
					GameObject val5 = null;
					GameObject val6 = null;
					try
					{
						Hand leftHand = physRig.leftHand;
						if ((Object)(object)((leftHand != null) ? leftHand.m_CurrentAttachedGO : null) != (Object)null)
						{
							val5 = ((Component)physRig.leftHand.m_CurrentAttachedGO.transform.root).gameObject;
						}
					}
					catch
					{
					}
					try
					{
						Hand rightHand = physRig.rightHand;
						if ((Object)(object)((rightHand != null) ? rightHand.m_CurrentAttachedGO : null) != (Object)null)
						{
							val6 = ((Component)physRig.rightHand.m_CurrentAttachedGO.transform.root).gameObject;
						}
					}
					catch
					{
					}
					Grip[] cachedRigGrips = _cachedRigGrips;
					foreach (Grip val7 in cachedRigGrips)
					{
						if ((Object)(object)val7 == (Object)null || !val7.HasAttachedHands() || IsTorsoGrip(val7, torso))
						{
							continue;
						}
						Transform root = ((Component)val7).transform.root;
						if (((Object)(object)val5 != (Object)null && (Object)(object)((Component)root).gameObject == (Object)(object)val5) || ((Object)(object)val6 != (Object)null && (Object)(object)((Component)root).gameObject == (Object)(object)val6) || (Object)(object)root != (Object)(object)transform)
						{
							continue;
						}
						RigManager externalGrabberFromGrip = GetExternalGrabberFromGrip(val7, rigManager);
						if ((Object)(object)externalGrabberFromGrip == (Object)null)
						{
							continue;
						}
						Transform transform2 = ((Component)val7).transform;
						if ((Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null)
						{
							float num = Vector3.Distance(transform2.position, val3.position);
							float num2 = Vector3.Distance(transform2.position, val4.position);
							if (transform2.IsChildOf(val3) || num < num2)
							{
								if ((Object)(object)val == (Object)null)
								{
									val = externalGrabberFromGrip;
								}
							}
							else if ((Object)(object)val2 == (Object)null)
							{
								val2 = externalGrabberFromGrip;
							}
							continue;
						}
						Vector3 val8 = transform.InverseTransformPoint(transform2.position);
						if (val8.x < 0f)
						{
							if ((Object)(object)val == (Object)null)
							{
								val = externalGrabberFromGrip;
							}
						}
						else if ((Object)(object)val2 == (Object)null)
						{
							val2 = externalGrabberFromGrip;
						}
					}
				}
				if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
				{
					float rigMass2 = GetRigMass(val);
					float rigMass3 = GetRigMass(val2);
					if (rigMass2 >= rigMass * 0.9f || rigMass3 >= rigMass * 0.9f)
					{
						TriggerRagdoll(rigManager, "Both Arms Grabbed", dropItems: false);
						return;
					}
				}
				int num3 = 0;
				RigManager val9 = null;
				Grip[] array = (Grip[])(object)new Grip[3] { torso.gChest, torso.gSpine, torso.gPelvis };
				Grip[] array2 = array;
				foreach (Grip val10 in array2)
				{
					if (!((Object)(object)val10 == (Object)null))
					{
						RigManager externalGrabber3 = GetExternalGrabber(val10, rigManager);
						if ((Object)(object)externalGrabber3 != (Object)null)
						{
							val9 = externalGrabber3;
							num3 += CountExternalHands(val10, rigManager);
						}
					}
				}
				if ((Object)(object)torso.gHead != (Object)null)
				{
					num3 += CountExternalHands(torso.gHead, rigManager);
				}
				if ((Object)(object)torso.gNeck != (Object)null)
				{
					num3 += CountExternalHands((Grip)(object)torso.gNeck, rigManager);
				}
				if ((Object)(object)val9 != (Object)null && num3 >= 1)
				{
					float num4 = GetRigMass(val9) / rigMass;
					if (num4 >= 2f && num3 >= 1)
					{
						TriggerRagdoll(rigManager, "Body Grabbed (Much Bigger)", dropItems: false);
					}
					else if (num4 >= 1.3f && num3 >= 2)
					{
						TriggerRagdoll(rigManager, "Body Grabbed (Both Hands)", dropItems: false);
					}
				}
			}
			catch
			{
			}
		}

		private static RigManager GetExternalGrabber(Grip grip, RigManager myRig)
		{
			if ((Object)(object)grip == (Object)null || !grip.HasAttachedHands())
			{
				return null;
			}
			return GetExternalGrabberFromGrip(grip, myRig);
		}

		private static RigManager GetExternalGrabberFromGrip(Grip grip, RigManager myRig)
		{
			try
			{
				List<Hand> attachedHands = grip.attachedHands;
				if (attachedHands == null)
				{
					return null;
				}
				for (int i = 0; i < attachedHands.Count; i++)
				{
					Hand val = attachedHands[i];
					if ((Object)(object)val != (Object)null && (Object)(object)val.manager != (Object)null && (Object)(object)val.manager != (Object)(object)myRig)
					{
						return val.manager;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static int CountExternalHands(Grip grip, RigManager myRig)
		{
			int num = 0;
			try
			{
				if ((Object)(object)grip == (Object)null || !grip.HasAttachedHands())
				{
					return 0;
				}
				List<Hand> attachedHands = grip.attachedHands;
				if (attachedHands == null)
				{
					return 0;
				}
				for (int i = 0; i < attachedHands.Count; i++)
				{
					Hand val = attachedHands[i];
					if ((Object)(object)val != (Object)null && (Object)(object)val.manager != (Object)null && (Object)(object)val.manager != (Object)(object)myRig)
					{
						num++;
					}
				}
			}
			catch
			{
			}
			return num;
		}

		private static bool IsTorsoGrip(Grip grip, PhysTorso torso)
		{
			return (Object)(object)grip == (Object)(object)torso.gHead || (Object)(object)grip == (Object)(object)torso.gNeck || (Object)(object)grip == (Object)(object)torso.gChest || (Object)(object)grip == (Object)(object)torso.gSpine || (Object)(object)grip == (Object)(object)torso.gPelvis;
		}

		private static float GetRigMass(RigManager rig)
		{
			try
			{
				if ((Object)(object)rig == (Object)null)
				{
					return 1f;
				}
				PhysicsRig physicsRig = rig.physicsRig;
				if ((Object)(object)physicsRig == (Object)null)
				{
					return 1f;
				}
				float num = 0f;
				PhysTorso torso = physicsRig.torso;
				if ((Object)(object)torso != (Object)null)
				{
					if ((Object)(object)torso.rbHead != (Object)null)
					{
						num += torso.rbHead.mass;
					}
					if ((Object)(object)torso.rbChest != (Object)null)
					{
						num += torso.rbChest.mass;
					}
					if ((Object)(object)torso.rbSpine != (Object)null)
					{
						num += torso.rbSpine.mass;
					}
					if ((Object)(object)torso.rbPelvis != (Object)null)
					{
						num += torso.rbPelvis.mass;
					}
				}
				if ((Object)(object)physicsRig.leftHand != (Object)null && (Object)(object)physicsRig.leftHand.rb != (Object)null)
				{
					num += physicsRig.leftHand.rb.mass;
				}
				if ((Object)(object)physicsRig.rightHand != (Object)null && (Object)(object)physicsRig.rightHand.rb != (Object)null)
				{
					num += physicsRig.rightHand.rb.mass;
				}
				return (num > 0f) ? num : 1f;
			}
			catch
			{
				return 1f;
			}
		}

		private static void RefreshGripCache(RigManager rigManager)
		{
			if (Time.time - _lastGripCacheTime < 2f && _cachedRigGrips != null)
			{
				return;
			}
			try
			{
				_cachedRigGrips = Il2CppArrayBase<Grip>.op_Implicit(((Component)rigManager).GetComponentsInChildren<Grip>());
				_lastGripCacheTime = Time.time;
			}
			catch
			{
				_cachedRigGrips = null;
			}
		}

		private static void TriggerRagdoll(RigManager rig, string reason, bool dropItems)
		{
			try
			{
				PhysicsRig physicsRig = rig.physicsRig;
				if (!((Object)(object)physicsRig == (Object)null))
				{
					ApplyRagdollMode(physicsRig);
					if (dropItems)
					{
						TryDrop(Player.LeftHand);
						TryDrop(Player.RightHand);
					}
					_nextRagdollTime = Time.time + 2f;
					MelonLogger.Msg($"Ragdoll triggered: {reason} ({_mode})");
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Ragdoll trigger error: " + ex.Message);
			}
		}

		private static void ApplyRagdollMode(PhysicsRig physRig)
		{
			if (_tantrumMode)
			{
				physRig.RagdollRig();
			}
			else if (_mode == RagdollMode.ARM_CONTROL)
			{
				physRig.legLf.ShutdownLimb();
				physRig.legRt.ShutdownLimb();
			}
			else
			{
				physRig.ShutdownRig();
				physRig.RagdollRig();
			}
		}

		private static void TryDrop(Hand hand)
		{
			try
			{
				if (!((Object)(object)hand == (Object)null) && hand.HasAttachedObject())
				{
					Grip val = ((Il2CppObjectBase)hand.AttachedReceiver).TryCast<Grip>();
					if (val != null)
					{
						val.ForceDetach(true);
					}
				}
			}
			catch
			{
			}
		}

		private static void OnPlayerDeathHook(RigManager rig)
		{
			if (!_enabled)
			{
				return;
			}
			try
			{
				PhysicsRig val = ((rig != null) ? rig.physicsRig : null);
				if ((Object)(object)val != (Object)null)
				{
					val.TurnOnRig();
					val.UnRagdollRig();
				}
				_ragdollCooldownUntil = Time.time + 2f;
			}
			catch
			{
			}
		}

		private static void OnPlayerResurrectedHook(RigManager rig)
		{
		}
	}
}