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)
{
}
}
}