Decompiled source of BetterRagdollEnhanced v1.2.1

plugins/BetterRagdollEnhanced.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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BetterRagdollEnhanced")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1+9a00a0fe2f4acd87a6dcf47c0d3cd54cc51f7292")]
[assembly: AssemblyProduct("BetterRagdollEnhanced")]
[assembly: AssemblyTitle("BetterRagdollEnhanced")]
[assembly: AssemblyVersion("1.2.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 BetterRagdollEnhanced
{
	internal sealed class GroundRollMotor
	{
		public void Step(GroundRollFrame frame, RollIntent intent, RagdollRollSettings settings)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: 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_010d: 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_0121: 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_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			if (settings.RollAcceleration <= 0f || settings.MaxRollSpeed <= 0f)
			{
				return;
			}
			float num = ((intent.Source == RollInputSource.Mouse) ? settings.MouseRollStrength : settings.GamepadRollStrength);
			if (num <= 0f)
			{
				return;
			}
			float targetSpeed = intent.Value * frame.InputDirection * settings.MaxRollSpeed;
			float num2 = settings.RollAcceleration * num * Time.fixedDeltaTime;
			float accelerationOnlyChange = RollMath.GetAccelerationOnlyChange(frame.AngularSpeed, targetSpeed, num2);
			float nextAngularSpeed = frame.AngularSpeed + accelerationOnlyChange;
			Vector3 centerVelocityChange = RollMath.GetCenterVelocityChange(frame.RollAxis, frame.ContactArm, nextAngularSpeed, frame.CenterVelocity, num2);
			Vector3 val = frame.RollAxis * accelerationOnlyChange;
			if (((Vector3)(ref val)).sqrMagnitude <= 0f && ((Vector3)(ref centerVelocityChange)).sqrMagnitude <= 0f)
			{
				return;
			}
			Rigidbody[] bodies = frame.Bodies;
			foreach (Rigidbody val2 in bodies)
			{
				if (!((Object)(object)val2 == (Object)null) && !val2.isKinematic)
				{
					Vector3 bodyOffset = val2.worldCenterOfMass - frame.Center;
					val2.angularVelocity += val;
					val2.linearVelocity += RollMath.GetBodyVelocityChange(val, bodyOffset, centerVelocityChange);
				}
			}
		}
	}
	[BepInPlugin("com.github.lllei.BetterRagdollEnhanced", "BetterRagdollEnhanced", "1.2.1")]
	[BepInIncompatibility("BetterRagdoll")]
	[DefaultExecutionOrder(1000)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.github.lllei.BetterRagdollEnhanced";

		public const string PluginName = "BetterRagdollEnhanced";

		public const string OriginalPluginGuid = "BetterRagdoll";

		private const float InitialFallSeconds = 0.5f;

		private const float RefreshFallSeconds = 0.2f;

		private const float RefreshThreshold = 0.08f;

		private const float RefreshInterval = 0.1f;

		private static readonly MethodInfo? CanDoInputMethod = FindCharacterMethod("CanDoInput", Type.EmptyTypes);

		private static readonly MethodInfo? FallMethod = FindCharacterMethod("Fall", typeof(float), typeof(float));

		private static readonly MethodInfo? AddForceMethod = FindCharacterMethod("AddForce", typeof(Vector3), typeof(float), typeof(float));

		private ConfigEntry<float> _force;

		private ConfigEntry<string> _keyboardBinding;

		private ConfigEntry<string> _gamepadBinding;

		private ConfigEntry<bool> _ragdollMovementEnabled;

		private ConfigEntry<float> _rollAcceleration;

		private ConfigEntry<float> _maxRollSpeed;

		private ConfigEntry<float> _mouseRollSensitivity;

		private ConfigEntry<float> _mouseRollStrength;

		private ConfigEntry<float> _gamepadRollSensitivity;

		private ConfigEntry<float> _gamepadRollStrength;

		private RagdollInput _ragdollInput;

		private RagdollRollController _rollController;

		private bool _isHolding;

		private bool _suppressUntilRelease;

		private bool _inputGateFailureLogged;

		private bool _movementPushFailureLogged;

		private float _nextRefreshAt;

		private void Awake()
		{
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Expected O, but got Unknown
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Expected O, but got Unknown
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Expected O, but got Unknown
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Expected O, but got Unknown
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Expected O, but got Unknown
			_rollController = new RagdollRollController(((BaseUnityPlugin)this).Logger);
			_force = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "Ragdoll Force", 322f, "Force applied in the movement direction when triggering ragdoll.");
			_keyboardBinding = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "Keyboard Ragdoll Key", "<Keyboard>/x", "Input System control path used to trigger ragdoll from a keyboard or mouse.");
			_gamepadBinding = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "Gamepad Ragdoll Key", "<Gamepad>/leftShoulder", "Input System control path used to trigger ragdoll from a gamepad.");
			_ragdollInput = new RagdollInput(((BaseUnityPlugin)this).Logger, _keyboardBinding.Value, _gamepadBinding.Value);
			_keyboardBinding.SettingChanged += OnRagdollBindingChanged;
			_gamepadBinding.SettingChanged += OnRagdollBindingChanged;
			_ragdollMovementEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Ragdoll Movement", "Enabled", true, "Allow horizontal look input to roll a grounded ragdoll triggered by this mod.");
			_rollAcceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Ragdoll Movement", "Roll Acceleration", 30f, new ConfigDescription("Maximum angular-speed change per second while rolling on the ground.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>()));
			_maxRollSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Ragdoll Movement", "Max Roll Speed", 4f, new ConfigDescription("Target side-roll angular speed in radians per second.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 15f), Array.Empty<object>()));
			_mouseRollSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("Ragdoll Movement", "Mouse Roll Sensitivity", 2f, new ConfigDescription("Scale applied to horizontal mouse movement used as an additional roll input.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			_mouseRollStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Ragdoll Movement", "Mouse Roll Strength", 5f, new ConfigDescription("Roll acceleration multiplier applied only to mouse input impulses.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			_gamepadRollSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("Ragdoll Movement", "Gamepad Roll Sensitivity", 1f, new ConfigDescription("Scale applied to horizontal right-stick input used for rolling.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			_gamepadRollStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Ragdoll Movement", "Gamepad Roll Strength", 3f, new ConfigDescription("Roll acceleration multiplier applied only to right-stick input.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			if (CanDoInputMethod == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Character.CanDoInput() was not found; ragdoll input is disabled to prevent UI input passthrough.");
			}
			if (FallMethod == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Character.Fall(float, float) was not found; using the Photon RPC fallback.");
			}
			if (AddForceMethod == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Character.AddForce(Vector3, float, float) was not found; the movement push is disabled.");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"BetterRagdollEnhanced 1.2.1 loaded.");
		}

		private void Update()
		{
			RagdollInputState ragdollInputState = _ragdollInput.Read();
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || !Application.isFocused || !CanUseInput(localCharacter))
			{
				_isHolding = false;
				_suppressUntilRelease = ragdollInputState.Held;
				_rollController.ClearInput();
				return;
			}
			if (_suppressUntilRelease)
			{
				if (ragdollInputState.Held)
				{
					_rollController.ClearInput();
					return;
				}
				_suppressUntilRelease = false;
			}
			if (ragdollInputState.Pressed)
			{
				_isHolding = true;
				_nextRefreshAt = Time.time + 0.1f;
				if (localCharacter.data.fallSeconds <= 0f && TriggerInitialFall(localCharacter))
				{
					_rollController.Begin(localCharacter);
					ApplyMovementPush(localCharacter);
				}
			}
			if (!ragdollInputState.Held && !ragdollInputState.Pressed)
			{
				_isHolding = false;
			}
			if (_isHolding && ragdollInputState.Held && localCharacter.data.fallSeconds <= 0.08f && Time.time >= _nextRefreshAt)
			{
				SendFallRpc(localCharacter, 0.2f);
				_nextRefreshAt = Time.time + 0.1f;
			}
			_rollController.SampleInput(_mouseRollSensitivity.Value, _gamepadRollSensitivity.Value);
		}

		private void FixedUpdate()
		{
			Character localCharacter = Character.localCharacter;
			bool inputAllowed = (Object)(object)localCharacter != (Object)null && Application.isFocused && !_suppressUntilRelease && CanUseInput(localCharacter);
			_rollController.Tick(localCharacter, inputAllowed, new RagdollRollSettings(_ragdollMovementEnabled.Value, _rollAcceleration.Value, _maxRollSpeed.Value, _mouseRollStrength.Value, _gamepadRollStrength.Value));
		}

		private void OnDestroy()
		{
			_keyboardBinding.SettingChanged -= OnRagdollBindingChanged;
			_gamepadBinding.SettingChanged -= OnRagdollBindingChanged;
			_ragdollInput?.Dispose();
			_rollController?.Reset();
		}

		private void OnRagdollBindingChanged(object sender, EventArgs eventArgs)
		{
			_ragdollInput.SetBindings(_keyboardBinding.Value, _gamepadBinding.Value);
			_isHolding = false;
			_suppressUntilRelease = _ragdollInput.Read().Held;
			_rollController.ClearInput();
		}

		private bool CanUseInput(Character character)
		{
			if (CanDoInputMethod == null || !character.IsPlayerControlled || (Object)(object)character.data == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || character.refs == null || (Object)(object)character.refs.view == (Object)null || (Object)(object)character.refs.ragdoll == (Object)null || character.data.dead || character.data.passedOut || character.data.fullyPassedOut)
			{
				return false;
			}
			try
			{
				return (bool)(CanDoInputMethod.Invoke(character, null) ?? ((object)false));
			}
			catch (Exception arg)
			{
				if (!_inputGateFailureLogged)
				{
					_inputGateFailureLogged = true;
					((BaseUnityPlugin)this).Logger.LogError((object)$"Character.CanDoInput() failed; ragdoll input is disabled: {arg}");
				}
				return false;
			}
		}

		private bool TriggerInitialFall(Character character)
		{
			try
			{
				if (FallMethod != null)
				{
					FallMethod.Invoke(character, new object[2] { 0.5f, 0f });
				}
				else
				{
					SendFallRpc(character, 0.5f);
				}
				return true;
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to trigger ragdoll: {arg}");
				return false;
			}
		}

		private void ApplyMovementPush(Character character)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			Vector3 avarageVelocity = character.data.avarageVelocity;
			if (((Vector3)(ref avarageVelocity)).sqrMagnitude < 0.01f)
			{
				return;
			}
			try
			{
				AddForceMethod?.Invoke(character, new object[3]
				{
					((Vector3)(ref avarageVelocity)).normalized * _force.Value,
					1f,
					1f
				});
			}
			catch (Exception arg)
			{
				if (!_movementPushFailureLogged)
				{
					_movementPushFailureLogged = true;
					((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to apply the initial ragdoll push; ragdoll movement remains available: {arg}");
				}
			}
		}

		private static void SendFallRpc(Character character, float seconds)
		{
			((MonoBehaviourPun)character).photonView.RPC("RPCA_Fall", (RpcTarget)0, new object[2] { seconds, 0f });
		}

		private static MethodInfo? FindCharacterMethod(string name, params Type[] parameterTypes)
		{
			return typeof(Character).GetMethod(name, BindingFlags.Instance | BindingFlags.NonPublic, null, parameterTypes, null);
		}
	}
	internal readonly struct RagdollInputState
	{
		public bool Pressed { get; }

		public bool Held { get; }

		public RagdollInputState(bool pressed, bool held)
		{
			Pressed = pressed;
			Held = held;
		}
	}
	internal sealed class RagdollInput : IDisposable
	{
		private readonly ManualLogSource _logger;

		private InputAction _action;

		public RagdollInput(ManualLogSource logger, string keyboardBinding, string gamepadBinding)
		{
			_logger = logger;
			_action = CreateAction(keyboardBinding, gamepadBinding);
		}

		public RagdollInputState Read()
		{
			return new RagdollInputState(_action.WasPressedThisFrame(), _action.IsPressed());
		}

		public void SetBindings(string keyboardBinding, string gamepadBinding)
		{
			InputAction action = _action;
			_action = CreateAction(keyboardBinding, gamepadBinding);
			action.Disable();
			action.Dispose();
		}

		public void Dispose()
		{
			_action.Disable();
			_action.Dispose();
		}

		private InputAction CreateAction(string keyboardBinding, string gamepadBinding)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			InputAction val = new InputAction("Ragdoll", (InputActionType)1, (string)null, (string)null, (string)null, "Button");
			AddBinding(val, "keyboard/mouse", keyboardBinding);
			AddBinding(val, "gamepad", gamepadBinding);
			val.Enable();
			return val;
		}

		private void AddBinding(InputAction action, string deviceName, string binding)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrWhiteSpace(binding))
			{
				_logger.LogInfo((object)("The " + deviceName + " ragdoll binding is disabled."));
				return;
			}
			try
			{
				InputActionSetupExtensions.AddBinding(action, binding, (string)null, (string)null, (string)null);
			}
			catch (ArgumentException ex)
			{
				_logger.LogWarning((object)("Ignoring invalid " + deviceName + " ragdoll binding '" + binding + "': " + ex.Message));
			}
		}
	}
	internal readonly struct RagdollRollSettings
	{
		public bool Enabled { get; }

		public float RollAcceleration { get; }

		public float MaxRollSpeed { get; }

		public float MouseRollStrength { get; }

		public float GamepadRollStrength { get; }

		public RagdollRollSettings(bool enabled, float rollAcceleration, float maxRollSpeed, float mouseRollStrength, float gamepadRollStrength)
		{
			Enabled = enabled;
			RollAcceleration = rollAcceleration;
			MaxRollSpeed = maxRollSpeed;
			MouseRollStrength = mouseRollStrength;
			GamepadRollStrength = gamepadRollStrength;
		}
	}
	internal sealed class RagdollRollController
	{
		private readonly ManualLogSource _logger;

		private readonly RollInputSampler _inputSampler = new RollInputSampler();

		private readonly GroundRollMotor _motor = new GroundRollMotor();

		private RagdollRollSession? _session;

		private bool _sessionFailureLogged;

		public RagdollRollController(ManualLogSource logger)
		{
			_logger = logger;
		}

		public void Begin(Character character)
		{
			Reset();
			if (RagdollRollSession.TryCreate(character, out RagdollRollSession session))
			{
				_session = session;
			}
			else if (!_sessionFailureLogged)
			{
				_sessionFailureLogged = true;
				_logger.LogError((object)"Grounded ragdoll rolling is disabled because required bodyparts or rigidbodies were not found.");
			}
		}

		public void SampleInput(float mouseRollSensitivity, float gamepadRollSensitivity)
		{
			if (_session != null)
			{
				_inputSampler.Sample(mouseRollSensitivity, gamepadRollSensitivity);
			}
		}

		public void ClearInput()
		{
			_inputSampler.Clear();
		}

		public void Tick(Character? localCharacter, bool inputAllowed, RagdollRollSettings settings)
		{
			if (_session == null)
			{
				return;
			}
			if (!_session.IsValid(localCharacter))
			{
				Reset();
				return;
			}
			if (!settings.Enabled || !inputAllowed)
			{
				ClearInput();
				return;
			}
			RollIntent intent = _inputSampler.Consume();
			if (intent.IsActive && _session.Character.data.isGrounded && _session.TryMeasure(out var frame))
			{
				_motor.Step(frame, intent, settings);
			}
		}

		public void Reset()
		{
			_session = null;
			ClearInput();
		}
	}
	internal readonly struct GroundRollFrame
	{
		public Rigidbody[] Bodies { get; }

		public Vector3 RollAxis { get; }

		public float InputDirection { get; }

		public Vector3 Center { get; }

		public Vector3 CenterVelocity { get; }

		public float AngularSpeed { get; }

		public Vector3 ContactArm { get; }

		public GroundRollFrame(Rigidbody[] bodies, Vector3 rollAxis, float inputDirection, Vector3 center, Vector3 centerVelocity, float angularSpeed, Vector3 contactArm)
		{
			//IL_0008: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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)
			Bodies = bodies;
			RollAxis = rollAxis;
			InputDirection = inputDirection;
			Center = center;
			CenterVelocity = centerVelocity;
			AngularSpeed = angularSpeed;
			ContactArm = contactArm;
		}
	}
	internal sealed class RagdollRollSession
	{
		private const float MinimumBodyAxisSqrMagnitude = 0.04f;

		private const float AxisDirectionHysteresis = 0.2f;

		private const float PostureDirectionHysteresis = 0.25f;

		private const float MinimumContactRadius = 0.2f;

		private const float MaximumContactRadius = 0.4f;

		private readonly Bodypart _hip;

		private readonly Bodypart _head;

		private readonly Bodypart _leftShoulder;

		private readonly Bodypart _rightShoulder;

		private readonly Rigidbody[] _bodies;

		private float? _axisDirection;

		private float? _inputDirection;

		public Character Character { get; }

		private RagdollRollSession(Character character, Bodypart hip, Bodypart head, Bodypart leftShoulder, Bodypart rightShoulder, Rigidbody[] bodies)
		{
			Character = character;
			_hip = hip;
			_head = head;
			_leftShoulder = leftShoulder;
			_rightShoulder = rightShoulder;
			_bodies = bodies;
		}

		public static bool TryCreate(Character character, out RagdollRollSession? session)
		{
			session = null;
			if (character.refs?.ragdoll?.partList == null)
			{
				return false;
			}
			Bodypart val = FindBodypart(character, (BodypartType)0);
			Bodypart val2 = FindBodypart(character, (BodypartType)4);
			Bodypart val3 = FindBodypart(character, (BodypartType)25) ?? FindBodypart(character, (BodypartType)5);
			Bodypart val4 = FindBodypart(character, (BodypartType)26) ?? FindBodypart(character, (BodypartType)8);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null)
			{
				return false;
			}
			List<Rigidbody> list = new List<Rigidbody>(character.refs.ragdoll.partList.Count);
			foreach (Bodypart part in character.refs.ragdoll.partList)
			{
				if ((Object)(object)((part != null) ? part.Rig : null) != (Object)null)
				{
					list.Add(part.Rig);
				}
			}
			if (list.Count == 0)
			{
				return false;
			}
			session = new RagdollRollSession(character, val, val2, val3, val4, list.ToArray());
			return true;
		}

		public bool IsValid(Character? localCharacter)
		{
			if ((Object)(object)localCharacter == (Object)(object)Character && (Object)(object)Character.data != (Object)null && Character.refs?.ragdoll?.partList != null && Character.data.fallSeconds > 0f && !Character.data.dead && !Character.data.passedOut)
			{
				return !Character.data.fullyPassedOut;
			}
			return false;
		}

		public bool TryMeasure(out GroundRollFrame frame)
		{
			//IL_003a: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_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_0068: 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_0086: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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_00fc: 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_0101: Unknown result type (might be due to invalid IL or missing references)
			frame = default(GroundRollFrame);
			Vector3 val = ((((Vector3)(ref Character.data.groundNormal)).sqrMagnitude > 0.5f) ? ((Vector3)(ref Character.data.groundNormal)).normalized : Vector3.up);
			Vector3 val2 = _head.transform.position - _hip.transform.position;
			Vector3 val3 = Vector3.ProjectOnPlane(val2, val);
			if (((Vector3)(ref val3)).sqrMagnitude < 0.04f)
			{
				return false;
			}
			((Vector3)(ref val3)).Normalize();
			if (!TryResolveDirections(val3, val, val2))
			{
				return false;
			}
			val3 *= _axisDirection.Value;
			if (!TryMeasureBodies(val3, out var center, out var centerVelocity, out var angularSpeed))
			{
				return false;
			}
			Vector3 contactArm = RollMath.GetContactArm(center, Character.data.groundPos, val3, val, 0.2f, 0.4f);
			if (((Vector3)(ref contactArm)).sqrMagnitude <= 0.01f)
			{
				return false;
			}
			frame = new GroundRollFrame(_bodies, val3, _inputDirection.Value, center, centerVelocity, angularSpeed, contactArm);
			return true;
		}

		private bool TryResolveDirections(Vector3 rollAxis, Vector3 groundNormal, Vector3 bodyAxis)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_007d: 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_0087: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (!_axisDirection.HasValue)
			{
				Vector3 cameraForward = Vector3.ProjectOnPlane(Character.data.lookDirection_Flat, groundNormal);
				if (!RollMath.TryGetAxisDirection(rollAxis, cameraForward, 0.2f, out var direction))
				{
					return false;
				}
				_axisDirection = direction;
			}
			if (_inputDirection.HasValue)
			{
				return true;
			}
			Vector3 rollAxis2 = rollAxis * _axisDirection.Value;
			Vector3 shoulderAxis = _rightShoulder.transform.position - _leftShoulder.transform.position;
			if (!RollMath.TryGetPostureDirection(rollAxis2, groundNormal, bodyAxis, shoulderAxis, 0.25f, out var direction2))
			{
				return false;
			}
			_inputDirection = direction2;
			return true;
		}

		private bool TryMeasureBodies(Vector3 rollAxis, out Vector3 center, out Vector3 centerVelocity, out float angularSpeed)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_00cf: 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_00db: 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_00e6: 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_0066: 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)
			//IL_0077: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			center = Vector3.zero;
			centerVelocity = Vector3.zero;
			angularSpeed = 0f;
			float num = 0f;
			Rigidbody[] bodies = _bodies;
			foreach (Rigidbody val in bodies)
			{
				if (!((Object)(object)val == (Object)null) && !val.isKinematic)
				{
					float num2 = Mathf.Max(val.mass, 0.001f);
					num += num2;
					center += val.worldCenterOfMass * num2;
					centerVelocity += val.linearVelocity * num2;
					angularSpeed += Vector3.Dot(val.angularVelocity, rollAxis) * num2;
				}
			}
			if (num <= 0f)
			{
				return false;
			}
			center /= num;
			centerVelocity /= num;
			angularSpeed /= num;
			return true;
		}

		private static Bodypart? FindBodypart(Character character, BodypartType bodypartType)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (!character.refs.ragdoll.partDict.TryGetValue(bodypartType, out var value))
			{
				return null;
			}
			return value;
		}
	}
	internal enum RollInputSource
	{
		Mouse,
		Gamepad
	}
	internal readonly struct RollIntent
	{
		public float Value { get; }

		public RollInputSource Source { get; }

		public bool IsActive => Mathf.Abs(Value) >= 0.01f;

		public RollIntent(float value, RollInputSource source)
		{
			Value = value;
			Source = source;
		}
	}
	internal sealed class RollInputSampler
	{
		private float _pendingMouseInput;

		private float _gamepadInput;

		public void Sample(float mouseRollSensitivity, float gamepadRollSensitivity)
		{
			Mouse current = Mouse.current;
			if (current != null && mouseRollSensitivity > 0f)
			{
				_pendingMouseInput = Mathf.Clamp(_pendingMouseInput + ((InputControl<float>)(object)((Vector2Control)((Pointer)current).delta).x).ReadValue() * mouseRollSensitivity, -1f, 1f);
			}
			Gamepad current2 = Gamepad.current;
			_gamepadInput = ((current2 != null) ? Mathf.Clamp(((InputControl<float>)(object)((Vector2Control)current2.rightStick).x).ReadValue() * gamepadRollSensitivity, -1f, 1f) : 0f);
		}

		public RollIntent Consume()
		{
			bool flag = Mathf.Abs(_pendingMouseInput) >= Mathf.Abs(_gamepadInput);
			RollIntent result = new RollIntent(flag ? _pendingMouseInput : _gamepadInput, (!flag) ? RollInputSource.Gamepad : RollInputSource.Mouse);
			_pendingMouseInput = 0f;
			return result;
		}

		public void Clear()
		{
			_pendingMouseInput = 0f;
			_gamepadInput = 0f;
		}
	}
	internal static class RollMath
	{
		public static float GetAccelerationOnlyChange(float currentSpeed, float targetSpeed, float maxSpeedChange)
		{
			if (targetSpeed > 0f)
			{
				if (!(currentSpeed < targetSpeed))
				{
					return 0f;
				}
				return Mathf.Min(targetSpeed - currentSpeed, maxSpeedChange);
			}
			if (!(currentSpeed > targetSpeed))
			{
				return 0f;
			}
			return Mathf.Max(targetSpeed - currentSpeed, 0f - maxSpeedChange);
		}

		public static bool TryGetAxisDirection(Vector3 rollAxis, Vector3 cameraForward, float minimumAlignment, out float direction)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			direction = 0f;
			if (((Vector3)(ref cameraForward)).sqrMagnitude <= 0.01f)
			{
				return false;
			}
			float num = Vector3.Dot(rollAxis, ((Vector3)(ref cameraForward)).normalized);
			if (Mathf.Abs(num) < minimumAlignment)
			{
				return false;
			}
			direction = Mathf.Sign(num);
			return true;
		}

		public static bool TryGetPostureDirection(Vector3 rollAxis, Vector3 groundNormal, Vector3 bodyAxis, Vector3 shoulderAxis, float minimumAlignment, out float direction)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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)
			//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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0052: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			direction = 0f;
			if (((Vector3)(ref bodyAxis)).sqrMagnitude <= 0.01f || ((Vector3)(ref shoulderAxis)).sqrMagnitude <= 0.01f)
			{
				return false;
			}
			Vector3 val = Vector3.Cross(((Vector3)(ref shoulderAxis)).normalized, ((Vector3)(ref bodyAxis)).normalized);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			val = Vector3.Cross(groundNormal, rollAxis);
			Vector3 normalized2 = ((Vector3)(ref val)).normalized;
			float num = Vector3.Dot(Vector3.Cross(rollAxis, normalized), normalized2);
			if (Mathf.Abs(num) < minimumAlignment)
			{
				return false;
			}
			direction = Mathf.Sign(num);
			return true;
		}

		public static Vector3 GetContactArm(Vector3 center, Vector3 groundPoint, Vector3 rollAxis, Vector3 groundNormal, float minimumRadius, float maximumRadius)
		{
			//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_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0031: 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_001d: 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_005f: 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)
			Vector3 val = Vector3.ProjectOnPlane(center - groundPoint, rollAxis);
			if (((Vector3)(ref val)).sqrMagnitude <= 0.01f || Vector3.Dot(val, groundNormal) <= 0f)
			{
				val = Vector3.ProjectOnPlane(groundNormal, rollAxis);
			}
			if (((Vector3)(ref val)).sqrMagnitude <= 0.01f)
			{
				return Vector3.zero;
			}
			float num = Mathf.Clamp(((Vector3)(ref val)).magnitude, minimumRadius, maximumRadius);
			return ((Vector3)(ref val)).normalized * num;
		}

		public static Vector3 GetCenterVelocityChange(Vector3 rollAxis, Vector3 contactArm, float nextAngularSpeed, Vector3 centerVelocity, float maxAngularSpeedChange)
		{
			//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_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_0020: 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_0026: 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_003d: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.Cross(rollAxis, contactArm);
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude <= 0.001f)
			{
				return Vector3.zero;
			}
			Vector3 val2 = val / magnitude;
			float currentSpeed = Vector3.Dot(centerVelocity, val2);
			float targetSpeed = nextAngularSpeed * magnitude;
			float accelerationOnlyChange = GetAccelerationOnlyChange(currentSpeed, targetSpeed, maxAngularSpeedChange * magnitude);
			return val2 * accelerationOnlyChange;
		}

		public static Vector3 GetBodyVelocityChange(Vector3 angularVelocityChange, Vector3 bodyOffset, Vector3 centerVelocityChange)
		{
			//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_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_0008: Unknown result type (might be due to invalid IL or missing references)
			return centerVelocityChange + Vector3.Cross(angularVelocityChange, bodyOffset);
		}
	}
	internal static class BuildInfo
	{
		internal const string Version = "1.2.1";
	}
}