using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BoneLib;
using BoneLib.BoneMenu;
using Il2CppSLZ.Marrow;
using Il2CppSystem.Collections.Generic;
using MelonLoader;
using MelonLoader.Preferences;
using Spinny;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(SpinnyMod), "Spinny", "1.0.0", "Lakatrazz", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: AssemblyDescription("Turns you with what you stand on or grab.")]
[assembly: AssemblyTitle("Spinny")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Spinny;
public class SpinnyMod : MelonMod
{
public const string Name = "Spinny";
public const string Author = "Lakatrazz";
public const string Description = "Turns you with what you stand on or grab.";
public const string Version = "1.0.0";
private static Grip[] _playerGrips = Array.Empty<Grip>();
private static bool _preferencesSetup = false;
private static float _targetSpin = 0f;
private static float _currentSpin = 0f;
public static MelonPreferences_Category MelonPrefCategory { get; private set; }
public static MelonPreferences_Entry<bool> MelonPrefEnabled { get; private set; }
public static MelonPreferences_Entry<bool> MelonPrefGroundRotation { get; private set; }
public static MelonPreferences_Entry<bool> MelonPrefGrabRotation { get; private set; }
public static MelonPreferences_Entry<bool> MelonPrefBeingGrabbedRotation { get; private set; }
public static bool Enabled { get; private set; }
public static bool GroundRotation { get; private set; }
public static bool GrabRotation { get; private set; }
public static bool BeingGrabbedRotation { get; private set; }
public static Page MainPage { get; private set; }
public static BoolElement EnabledElement { get; private set; }
public static BoolElement GroundRotationElement { get; private set; }
public static BoolElement GrabRotationElement { get; private set; }
public static BoolElement BeingGrabbedRotationElement { get; private set; }
public override void OnInitializeMelon()
{
Hooking.OnLevelLoaded += OnLevelLoaded;
SetupMelonPrefs();
SetupBoneMenu();
}
private void OnLevelLoaded(LevelInfo info)
{
PhysicsRig physicsRig = Player.PhysicsRig;
PhysTorso torso = physicsRig.torso;
PhysHand physHand = physicsRig.leftHand.physHand;
PhysHand physHand2 = physicsRig.rightHand.physHand;
_playerGrips = (Grip[])(object)new Grip[9]
{
torso.gChest,
torso.gHead,
(Grip)torso.gNeck,
torso.gPelvis,
torso.gSpine,
(Grip)physHand.gShoulder,
(Grip)physHand.gElbow,
(Grip)physHand2.gShoulder,
(Grip)physHand2.gElbow
};
}
public static void SetupMelonPrefs()
{
MelonPrefCategory = MelonPreferences.CreateCategory("Spinny");
MelonPrefEnabled = MelonPrefCategory.CreateEntry<bool>("Enabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
MelonPrefGroundRotation = MelonPrefCategory.CreateEntry<bool>("Ground Rotation", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
MelonPrefGrabRotation = MelonPrefCategory.CreateEntry<bool>("Grab Rotation", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
MelonPrefBeingGrabbedRotation = MelonPrefCategory.CreateEntry<bool>("Being Grabbed Rotation", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
Enabled = MelonPrefEnabled.Value;
GroundRotation = MelonPrefGroundRotation.Value;
GrabRotation = MelonPrefGrabRotation.Value;
BeingGrabbedRotation = MelonPrefBeingGrabbedRotation.Value;
_preferencesSetup = true;
}
public static void SetupBoneMenu()
{
//IL_000a: 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_004f: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
MainPage = Page.Root.CreatePage("Spinny", Color.green, 0, true);
EnabledElement = MainPage.CreateBool("Enabled", Color.yellow, Enabled, (Action<bool>)OnSetEnabled);
GroundRotationElement = MainPage.CreateBool("Ground Rotation", Color.yellow, GroundRotation, (Action<bool>)OnSetGroundRotation);
GrabRotationElement = MainPage.CreateBool("Grab Rotation", Color.yellow, GrabRotation, (Action<bool>)OnSetGrabRotation);
BeingGrabbedRotationElement = MainPage.CreateBool("Being Grabbed Rotation", Color.yellow, BeingGrabbedRotation, (Action<bool>)OnSetBeingGrabbedRotation);
}
private static void OnSetEnabled(bool value)
{
Enabled = value;
MelonPrefEnabled.Value = value;
MelonPrefCategory.SaveToFile(false);
}
private static void OnSetGroundRotation(bool value)
{
GroundRotation = value;
MelonPrefGroundRotation.Value = value;
MelonPrefCategory.SaveToFile(false);
}
private static void OnSetGrabRotation(bool value)
{
GrabRotation = value;
MelonPrefGrabRotation.Value = value;
MelonPrefCategory.SaveToFile(false);
}
private static void OnSetBeingGrabbedRotation(bool value)
{
BeingGrabbedRotation = value;
MelonPrefBeingGrabbedRotation.Value = value;
MelonPrefCategory.SaveToFile(false);
}
public override void OnPreferencesLoaded()
{
if (_preferencesSetup)
{
Enabled = MelonPrefEnabled.Value;
GroundRotation = MelonPrefGroundRotation.Value;
GrabRotation = MelonPrefGrabRotation.Value;
EnabledElement.Value = Enabled;
GroundRotationElement.Value = GroundRotation;
GrabRotationElement.Value = GrabRotation;
}
}
public override void OnUpdate()
{
if (!Enabled)
{
return;
}
RigManager rigManager = Player.RigManager;
if ((Object)(object)rigManager == (Object)null)
{
return;
}
PhysicsRig physicsRig = rigManager.physicsRig;
if (!physicsRig.ballLocoEnabled)
{
_targetSpin = 0f;
_currentSpin = 0f;
return;
}
float decay = 12f;
_targetSpin = 0f;
if (CheckGrounded(physicsRig))
{
if (GroundRotation)
{
SolveGroundRotation(physicsRig);
}
}
else if (BeingGrabbedRotation && CheckBeingGrabbed())
{
SolveBeingGrabbedRotation();
}
else if (GrabRotation && CheckGrabbing(physicsRig))
{
SolveGrabRotation(physicsRig);
}
else
{
decay = 2f;
}
_currentSpin = Mathf.Lerp(_currentSpin, _targetSpin, Smoothing.CalculateDecay(decay, Time.deltaTime));
rigManager.remapHeptaRig.SetTwist(_currentSpin * 57.29578f);
}
private static bool CheckGrounded(PhysicsRig physicsRig)
{
return physicsRig.physG.isGrounded;
}
private static bool CheckGrabbing(PhysicsRig physicsRig)
{
if (!Object.op_Implicit((Object)(object)physicsRig.leftHand.m_CurrentAttachedGO))
{
return Object.op_Implicit((Object)(object)physicsRig.rightHand.m_CurrentAttachedGO);
}
return true;
}
private static bool CheckBeingGrabbed()
{
Grip[] playerGrips = _playerGrips;
for (int i = 0; i < playerGrips.Length; i++)
{
if (playerGrips[i].HasAttachedHands())
{
return true;
}
}
return false;
}
private static void SolveGroundRotation(PhysicsRig physicsRig)
{
float num = physicsRig.groundAngVelocity * Time.deltaTime;
Collider groundedCollider = physicsRig.physG._groundedCollider;
if ((Object)(object)groundedCollider != (Object)null && Object.op_Implicit((Object)(object)groundedCollider.attachedRigidbody))
{
num *= CalculateMassSupport(groundedCollider.attachedRigidbody);
}
_targetSpin = num;
}
private static void SolveBeingGrabbedRotation()
{
float num = 0f;
int num2 = 0;
Grip[] playerGrips = _playerGrips;
foreach (Grip val in playerGrips)
{
if (val.HasAttachedHands())
{
num += GetBeingGrabbedAngularVelocity(val);
num2++;
}
}
if (num2 > 0)
{
num /= (float)num2;
_targetSpin = num * Time.deltaTime;
}
}
private static float GetBeingGrabbedAngularVelocity(Grip grip)
{
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
float massArm = Player.RigManager.avatar.massArm;
float num = 0f;
int num2 = 0;
Enumerator<Hand> enumerator = grip.attachedHands.GetEnumerator();
while (enumerator.MoveNext())
{
Hand current = enumerator.Current;
PhysHand physHand = current.physHand;
float num3 = Mathf.Clamp01((physHand._upperArmRb.mass + physHand._lowerArmRb.mass + physHand._handRb.mass) / (massArm * 2f));
num += current.physHand._upperArmRb.angularVelocity.y * num3;
num2++;
}
return num / (float)num2;
}
private static void SolveGrabRotation(PhysicsRig physicsRig)
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
(float, float, Rigidbody) grabContribution = GetGrabContribution(physicsRig.leftHand);
(float, float, Rigidbody) grabContribution2 = GetGrabContribution(physicsRig.rightHand);
float num = grabContribution.Item1 + grabContribution2.Item1;
if (!(num <= 0f))
{
float num2 = grabContribution.Item1 / num;
float num3 = grabContribution2.Item1 / num;
float num4 = grabContribution.Item2 * num2;
float num5 = grabContribution2.Item2 * num3;
_targetSpin = (num4 + num5) * Time.deltaTime;
if (Object.op_Implicit((Object)(object)grabContribution.Item3))
{
grabContribution.Item3.AddTorque(Vector3.up * (0f - num4) * 0.2f, (ForceMode)2);
}
if (Object.op_Implicit((Object)(object)grabContribution2.Item3))
{
grabContribution2.Item3.AddTorque(Vector3.up * (0f - num5) * 0.2f, (ForceMode)2);
}
}
}
private static (float supported, float angularVelocity, Rigidbody rigidbody) GetGrabContribution(Hand hand)
{
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)hand.m_CurrentAttachedGO == (Object)null)
{
return (0f, 0f, null);
}
Grip val = Grip.Cache.Get(hand.m_CurrentAttachedGO);
if ((Object)(object)val == (Object)null)
{
return (0f, 0f, null);
}
IGrippable host = ((HandReciever)val).Host;
if (host == null || !host.HasRigidbody)
{
return (0f, 0f, null);
}
Rigidbody rb = host.Rb;
float y = rb.angularVelocity.y;
float num = CalculateMassSupport(rb);
float item = Mathf.Abs(hand.physHand.handSupported) * num;
y *= num;
return (item, y, rb);
}
private static float CalculateMassSupport(Rigidbody rigidbody)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
float massPelvis = Player.RigManager.avatar.massPelvis;
float y = rigidbody.angularVelocity.y;
float num = Mathf.Pow(rigidbody.mass / massPelvis, 4f);
float num2 = Mathf.Abs(y) / 10f + 1f;
num2 *= num2;
return Mathf.Clamp01(num * num2);
}
}
public static class Smoothing
{
public static float CalculateDecay(float decay, float deltaTime)
{
return 1f - Mathf.Exp((0f - decay) * deltaTime);
}
}