Decompiled source of ImprovedCharacterPhysics v1.9.7

ImprovedCharacterPhysics.dll

Decompiled 5 days ago
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using HarmonyLib;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ImprovedCharacterPhysics")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ImprovedCharacterPhysics")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8f40caaf-d3bb-483d-8cda-37a323a87a4a")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ImprovedCharacterPhysics;

[BepInPlugin("com.m4gmar.ImprovedCharacterPhysics", "Improved Character Physics Mod", "1.9.7")]
public class ImprovedCharacterPhysics : BaseUnityPlugin
{
	public PhysicMaterial floorPhyMaterial;

	private ConfigurableJoint HipStabilizer;

	private List<ConfigurableJoint> shoulderJoints = new List<ConfigurableJoint>();

	private List<ConfigurableJoint> elbowJoints = new List<ConfigurableJoint>();

	private List<ConfigurableJoint> hipJoints = new List<ConfigurableJoint>();

	private List<ConfigurableJoint> kneeJoints = new List<ConfigurableJoint>();

	private List<ConfigurableJoint> spineJoints = new List<ConfigurableJoint>();

	private List<ConfigurableJoint> hipStabilizerJoints = new List<ConfigurableJoint>();

	private float[] shoulderStamina;

	private float[] elbowStamina;

	private float[] hipStamina;

	private float[] kneeStamina;

	private float[] spineStamina;

	private Quaternion[] prevShoulderRotations;

	private Quaternion[] prevElbowRotations;

	private Quaternion[] prevHipRotations;

	private Quaternion[] prevKneeRotations;

	private Quaternion[] prevSpineRotations;

	private Quaternion[] StartingHipStabilizerRotations;

	private Dictionary<string, PlayerHealth> playerHealths = new Dictionary<string, PlayerHealth>();

	private Dictionary<string, float> playerCardioStamina = new Dictionary<string, float>();

	private Dictionary<string, int> jointFrameCount = new Dictionary<string, int>();

	private Dictionary<ConfigurableJoint, float> originalPositionSprings = new Dictionary<ConfigurableJoint, float>();

	private Dictionary<ConfigurableJoint, float> originalPositionDampers = new Dictionary<ConfigurableJoint, float>();

	private Dictionary<ConfigurableJoint, float> originalMaximumForces = new Dictionary<ConfigurableJoint, float>();

	private float updateInterval = 0.1f;

	private bool showMenu = false;

	private InputAction toggleMenuAction;

	public bool useMod = true;

	public bool useCustomHipStabilizer = true;

	public float hipStabilizerStrengthMultiplier = 100f;

	public float hipStabilizerDamperMultiplier = 100f;

	public float armStrenghtMultiplier = 100f;

	public float legStrengthMultiplier = 100f;

	public float spineStrenghtMultiplier = 100f;

	public float minMovementSpeedToDrainStamina = 110f;

	public float armsStaminaDrainMultiplier = 50f;

	public float armsStaminaRegenMultiplier = 100f;

	public float legsStaminaDrainMultiplier = 120f;

	public float legsStaminaRegenMultiplier = 100f;

	public float cardioVascularStaminaDrainMultiplier = 80f;

	public float cardioVascularStaminaRegenMultiplier = 40f;

	public float floorFriction = 60f;

	public void Awake()
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Expected O, but got Unknown
		((Object)Chainloader.ManagerObject).hideFlags = (HideFlags)61;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"AWAKE: Hooking into SceneManager.sceneLoaded");
		Harmony val = new Harmony("com.m4gmar.ImprovedCharacterPhysics");
		val.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Harmony patches applied.");
		SceneManager.sceneLoaded += OnSceneLoaded;
	}

	private void OnEnable()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Expected O, but got Unknown
		toggleMenuAction = new InputAction("ToggleMenu", (InputActionType)1, "<Keyboard>/f8", (string)null, (string)null, (string)null);
		toggleMenuAction.performed += delegate
		{
			ToggleMenu();
		};
		toggleMenuAction.Enable();
	}

	private void OnDisable()
	{
		toggleMenuAction.Disable();
		toggleMenuAction.performed -= delegate
		{
			ToggleMenu();
		};
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)("SCENE LOADED: " + ((Scene)(ref scene)).name));
		((MonoBehaviour)this).StopAllCoroutines();
		if (((Scene)(ref scene)).name.ToLower().Contains("map") || ((Scene)(ref scene)).name.ToLower().Contains("test"))
		{
			shoulderJoints.Clear();
			elbowJoints.Clear();
			hipJoints.Clear();
			kneeJoints.Clear();
			spineJoints.Clear();
			hipStabilizerJoints.Clear();
			playerHealths.Clear();
			playerCardioStamina.Clear();
			jointFrameCount.Clear();
			originalPositionSprings.Clear();
			originalPositionDampers.Clear();
			originalMaximumForces.Clear();
			shoulderStamina = null;
			elbowStamina = null;
			hipStamina = null;
			kneeStamina = null;
			spineStamina = null;
			prevShoulderRotations = null;
			prevElbowRotations = null;
			prevHipRotations = null;
			prevKneeRotations = null;
			prevSpineRotations = null;
			updateInterval = 0.1f;
			if (useMod)
			{
				((MonoBehaviour)this).StartCoroutine(WaitForPlayerObjects());
			}
		}
	}

	private IEnumerator WaitForPlayerObjects()
	{
		yield return (object)new WaitForSeconds(0.5f);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ObjectsLoaded, running Mod");
		ChangeFloorPhysicsMaterial();
		PlayerHealth[] playersHealth = Object.FindObjectsOfType<PlayerHealth>();
		PlayerHealth[] array = playersHealth;
		foreach (PlayerHealth playerHealth in array)
		{
			List<Transform> parentHierarchy = new List<Transform>();
			Transform current = ((Component)playerHealth).transform;
			while ((Object)(object)current.parent != (Object)null)
			{
				parentHierarchy.Add(current.parent);
				current = current.parent;
			}
			GameObject character;
			if (parentHierarchy.Count >= 3)
			{
				character = ((Component)parentHierarchy[parentHierarchy.Count - 3]).gameObject;
				Debug.Log((object)("Found Character: " + ((Object)character).name));
			}
			else
			{
				character = ((Component)playerHealth).gameObject;
				Debug.Log((object)("Found Character " + ((Object)((Component)playerHealth).gameObject).name));
			}
			if (!playerHealths.ContainsKey(((Object)character).name))
			{
				playerHealths.Add(((Object)character).name, playerHealth);
				playerCardioStamina.Add(((Object)character).name, 100f);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Added player " + ((Object)character).name + " with 100 cardio stamina."));
			}
		}
		foreach (ConfigurableJoint item in Object.FindObjectsOfType<ConfigurableJoint>().ToList())
		{
			if (!((Object)(object)item == (Object)null) && !((Object)(object)((Joint)item).connectedBody == (Object)null) && !((Object)(object)((Component)((Joint)item).connectedBody).gameObject == (Object)null))
			{
				JointDrive val;
				if (((Object)((Component)((Joint)item).connectedBody).gameObject).name == "HipSphere" && useCustomHipStabilizer)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"HipStabilizer FOUND!!!, Switching to CustomStabilizer");
					val = default(JointDrive);
					((JointDrive)(ref val)).positionSpring = 10000f;
					((JointDrive)(ref val)).positionDamper = 2700f * (hipStabilizerDamperMultiplier / 100f);
					((JointDrive)(ref val)).maximumForce = float.MaxValue;
					item.angularXDrive = val;
					val = default(JointDrive);
					((JointDrive)(ref val)).positionSpring = 10000f;
					((JointDrive)(ref val)).positionDamper = 2700f * (hipStabilizerDamperMultiplier / 100f);
					((JointDrive)(ref val)).maximumForce = 2500f * (hipStabilizerStrengthMultiplier / 100f);
					item.angularYZDrive = val;
					HipStabilizer = item;
					Dictionary<ConfigurableJoint, float> dictionary = originalPositionSprings;
					val = item.angularXDrive;
					dictionary[item] = ((JointDrive)(ref val)).positionSpring;
					Dictionary<ConfigurableJoint, float> dictionary2 = originalPositionDampers;
					val = item.angularXDrive;
					dictionary2[item] = ((JointDrive)(ref val)).positionDamper;
					Dictionary<ConfigurableJoint, float> dictionary3 = originalMaximumForces;
					val = item.angularXDrive;
					dictionary3[item] = ((JointDrive)(ref val)).maximumForce;
				}
				_ = ((Object)((Component)((Component)((Joint)item).connectedBody).gameObject.transform.root).gameObject).name;
				switch (((Object)((Component)((Joint)item).connectedBody).gameObject).name.ToLower())
				{
				case "shoulder_left":
					((BaseUnityPlugin)this).Logger.LogInfo((object)"ShoulderLeft Joint Found!!!");
					shoulderJoints.Add(item);
					originalPositionSprings[item] = 1700f;
					originalPositionDampers[item] = 150f;
					originalMaximumForces[item] = 650f * (armStrenghtMultiplier / 100f);
					break;
				case "shoulder_right":
					((BaseUnityPlugin)this).Logger.LogInfo((object)"ShoulderRight Joint Found!!!");
					shoulderJoints.Add(item);
					originalPositionSprings[item] = 1700f;
					originalPositionDampers[item] = 150f;
					originalMaximumForces[item] = 650f * (armStrenghtMultiplier / 100f);
					break;
				case "elbow_left":
					((BaseUnityPlugin)this).Logger.LogInfo((object)"ElbowLeft Joint Found!!!");
					elbowJoints.Add(item);
					originalPositionSprings[item] = 1700f;
					originalPositionDampers[item] = 150f;
					originalMaximumForces[item] = 475f * (armStrenghtMultiplier / 100f);
					break;
				case "elbow_right":
					((BaseUnityPlugin)this).Logger.LogInfo((object)"ElbowRight Joint Found!!!");
					elbowJoints.Add(item);
					originalPositionSprings[item] = 1700f;
					originalPositionDampers[item] = 150f;
					originalMaximumForces[item] = 475f * (armStrenghtMultiplier / 100f);
					break;
				case "hip_joint_left":
					((BaseUnityPlugin)this).Logger.LogInfo((object)"HipJointLeft Joint Found!!!");
					hipJoints.Add(item);
					originalPositionSprings[item] = 10000f;
					originalPositionDampers[item] = 900f;
					originalMaximumForces[item] = 1500f * (legStrengthMultiplier / 100f);
					break;
				case "hip_joint_right":
					((BaseUnityPlugin)this).Logger.LogInfo((object)"HipJointRight Joint Found!!!");
					hipJoints.Add(item);
					originalPositionSprings[item] = 10000f;
					originalPositionDampers[item] = 900f;
					originalMaximumForces[item] = 1500f * (legStrengthMultiplier / 100f);
					break;
				case "knee_left":
					((BaseUnityPlugin)this).Logger.LogInfo((object)"KneeLeft Joint Found!!!");
					kneeJoints.Add(item);
					originalPositionSprings[item] = 10000f;
					originalPositionDampers[item] = 900f;
					originalMaximumForces[item] = 1500f * (legStrengthMultiplier / 100f);
					break;
				case "knee_right":
					((BaseUnityPlugin)this).Logger.LogInfo((object)"KneeRight Joint Found!!!");
					kneeJoints.Add(item);
					originalPositionSprings[item] = 10000f;
					originalPositionDampers[item] = 900f;
					originalMaximumForces[item] = 1500f * (legStrengthMultiplier / 100f);
					break;
				case "spine1":
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Spine1 Joint Found!!! Skipping stamina system.");
					spineJoints.Add(item);
					val = default(JointDrive);
					((JointDrive)(ref val)).positionDamper = 650f;
					((JointDrive)(ref val)).positionSpring = 7000f;
					((JointDrive)(ref val)).maximumForce = 1500f * (spineStrenghtMultiplier / 100f);
					item.angularXDrive = val;
					val = default(JointDrive);
					((JointDrive)(ref val)).positionDamper = 650f;
					((JointDrive)(ref val)).positionSpring = 7000f;
					((JointDrive)(ref val)).maximumForce = 1500f * (spineStrenghtMultiplier / 100f);
					item.angularYZDrive = val;
					break;
				case "spine2":
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Spine2 Joint Found!!! Skipping stamina system.");
					spineJoints.Add(item);
					val = default(JointDrive);
					((JointDrive)(ref val)).positionDamper = 650f;
					((JointDrive)(ref val)).positionSpring = 7000f;
					((JointDrive)(ref val)).maximumForce = 1500f * (spineStrenghtMultiplier / 100f);
					item.angularXDrive = val;
					val = default(JointDrive);
					((JointDrive)(ref val)).positionDamper = 650f;
					((JointDrive)(ref val)).positionSpring = 7000f;
					((JointDrive)(ref val)).maximumForce = 1500f * (spineStrenghtMultiplier / 100f);
					item.angularYZDrive = val;
					break;
				case "hipsphere":
					((BaseUnityPlugin)this).Logger.LogInfo((object)"HipStabilizer Joint Found!!! Skipping stamina system.");
					hipStabilizerJoints.Add(item);
					break;
				}
			}
		}
		shoulderStamina = new float[shoulderJoints.Count];
		elbowStamina = new float[elbowJoints.Count];
		hipStamina = new float[hipJoints.Count];
		kneeStamina = new float[kneeJoints.Count];
		spineStamina = new float[spineJoints.Count];
		prevShoulderRotations = (Quaternion[])(object)new Quaternion[shoulderJoints.Count];
		prevElbowRotations = (Quaternion[])(object)new Quaternion[elbowJoints.Count];
		prevHipRotations = (Quaternion[])(object)new Quaternion[hipJoints.Count];
		prevKneeRotations = (Quaternion[])(object)new Quaternion[kneeJoints.Count];
		prevSpineRotations = (Quaternion[])(object)new Quaternion[spineJoints.Count];
		StartingHipStabilizerRotations = (Quaternion[])(object)new Quaternion[hipStabilizerJoints.Count];
		for (int i = 0; i < hipStabilizerJoints.Count; i++)
		{
			StartingHipStabilizerRotations[i] = ((Component)((Joint)hipStabilizerJoints[i]).connectedBody).transform.rotation;
		}
		for (int j = 0; j < shoulderJoints.Count; j++)
		{
			shoulderStamina[j] = 100f;
			prevShoulderRotations[j] = ((Component)shoulderJoints[j]).transform.localRotation * Quaternion.Inverse(shoulderJoints[j].targetRotation);
		}
		for (int l = 0; l < elbowJoints.Count; l++)
		{
			elbowStamina[l] = 100f;
			prevElbowRotations[l] = ((Component)elbowJoints[l]).transform.localRotation * Quaternion.Inverse(elbowJoints[l].targetRotation);
		}
		for (int m = 0; m < hipJoints.Count; m++)
		{
			hipStamina[m] = 100f;
			prevHipRotations[m] = ((Component)hipJoints[m]).transform.localRotation * Quaternion.Inverse(hipJoints[m].targetRotation);
		}
		for (int n = 0; n < kneeJoints.Count; n++)
		{
			kneeStamina[n] = 100f;
			prevKneeRotations[n] = ((Component)kneeJoints[n]).transform.localRotation * Quaternion.Inverse(kneeJoints[n].targetRotation);
		}
		for (int k = 0; k < spineJoints.Count; k++)
		{
			spineStamina[k] = 100f;
			prevSpineRotations[k] = ((Component)spineJoints[k]).transform.localRotation * Quaternion.Inverse(spineJoints[k].targetRotation);
		}
		updateInterval = (updateInterval * (float)(elbowJoints.Count / 2) + updateInterval) / 2f;
		((BaseUnityPlugin)this).Logger.LogError((object)$"update interval is {updateInterval}");
		((MonoBehaviour)this).StartCoroutine(UpdateStaminaCoroutine());
	}

	private IEnumerator UpdateStaminaCoroutine()
	{
		while (true)
		{
			for (int m = 0; m < shoulderJoints.Count; m++)
			{
				if ((Object)(object)shoulderJoints[m] != (Object)null)
				{
					CheckAndUpdateStamina(shoulderJoints[m], ref shoulderStamina[m], ref prevShoulderRotations[m]);
				}
			}
			for (int l = 0; l < elbowJoints.Count; l++)
			{
				if ((Object)(object)elbowJoints[l] != (Object)null)
				{
					CheckAndUpdateStamina(elbowJoints[l], ref elbowStamina[l], ref prevElbowRotations[l]);
				}
			}
			for (int k = 0; k < hipJoints.Count; k++)
			{
				if ((Object)(object)hipJoints[k] != (Object)null)
				{
					CheckAndUpdateStamina(hipJoints[k], ref hipStamina[k], ref prevHipRotations[k]);
				}
			}
			for (int j = 0; j < kneeJoints.Count; j++)
			{
				if ((Object)(object)kneeJoints[j] != (Object)null)
				{
					CheckAndUpdateStamina(kneeJoints[j], ref kneeStamina[j], ref prevKneeRotations[j]);
				}
			}
			for (int i = 0; i < hipStabilizerJoints.Count; i++)
			{
				if ((Object)(object)kneeJoints[i] != (Object)null)
				{
					HipStabilizerCalculator(hipStabilizerJoints[i], ref StartingHipStabilizerRotations[i]);
				}
			}
			yield return (object)new WaitForSeconds(updateInterval);
		}
	}

	private void CheckAndUpdateStamina(ConfigurableJoint joint, ref float stamina, ref Quaternion prevRotation)
	{
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0842: Unknown result type (might be due to invalid IL or missing references)
		//IL_084d: Unknown result type (might be due to invalid IL or missing references)
		//IL_08be: Unknown result type (might be due to invalid IL or missing references)
		//IL_06de: Unknown result type (might be due to invalid IL or missing references)
		//IL_0749: Unknown result type (might be due to invalid IL or missing references)
		//IL_0754: Unknown result type (might be due to invalid IL or missing references)
		//IL_07bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0931: Unknown result type (might be due to invalid IL or missing references)
		//IL_095e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0969: Unknown result type (might be due to invalid IL or missing references)
		//IL_0996: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)joint == (Object)null || (Object)(object)((Joint)joint).connectedBody == (Object)null || (Object)(object)((Component)((Joint)joint).connectedBody).gameObject == (Object)null)
		{
			return;
		}
		string name = ((Object)((Component)((Component)((Joint)joint).connectedBody).gameObject.transform.root).gameObject).name;
		Transform val = null;
		List<Transform> list = new List<Transform>();
		Transform val2 = ((Component)joint).transform;
		while (!((Object)val2).name.ToLower().Contains("character"))
		{
			list.Add(val2.parent);
			if (((Object)val2).name.ToLower() == "hip")
			{
				val = val2;
			}
			val2 = val2.parent;
		}
		name = ((Object)val2).name;
		if (!playerCardioStamina.ContainsKey(name))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Player " + name + " not found in playerCardioStamina dictionary."));
		}
		else
		{
			if (!((Object)(object)joint != (Object)null))
			{
				return;
			}
			Vector3 val3 = val.InverseTransformDirection(((Joint)joint).connectedBody.angularVelocity);
			float num = ((Vector3)(ref val3)).magnitude * 57.29578f;
			float num2 = num * updateInterval;
			if (num2 > minMovementSpeedToDrainStamina * updateInterval)
			{
				if (playerCardioStamina.ContainsKey(name))
				{
					if (((Object)((Joint)joint).connectedBody).name.ToLower().Contains("knee") || ((Object)((Joint)joint).connectedBody).name.ToLower().Contains("hip"))
					{
						float num3 = num2 / (20f * Mathf.Max(Mathf.Abs(playerCardioStamina[name] - 50f) / 50f, 0.1f)) * (cardioVascularStaminaDrainMultiplier / 500f) * (legsStaminaDrainMultiplier / 100f);
						playerCardioStamina[name] -= num3;
						playerCardioStamina[name] = Mathf.Clamp(playerCardioStamina[name], 0.01f, 100f);
					}
					else
					{
						float num4 = num2 / (20f * Mathf.Max(Mathf.Abs(playerCardioStamina[name] - 50f) / 50f, 0.1f)) * (cardioVascularStaminaDrainMultiplier / 500f) * (armsStaminaDrainMultiplier / 100f);
						playerCardioStamina[name] -= num4;
						playerCardioStamina[name] = Mathf.Clamp(playerCardioStamina[name], 0.01f, 100f);
					}
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("CardioVascularStamina for " + name + " wasn't found because " + name + " is not part of the PlayerList"));
				}
				if (((Object)((Joint)joint).connectedBody).name.ToLower().Contains("knee") || ((Object)((Joint)joint).connectedBody).name.ToLower().Contains("hip"))
				{
					stamina -= num2 / (20f * Mathf.Max(Mathf.Abs(stamina - 50f) / 50f, 0.1f)) * (legsStaminaDrainMultiplier / 100f);
					stamina = Mathf.Clamp(stamina, 0.01f, 100f);
				}
				else
				{
					stamina -= num2 / (20f * Mathf.Max(Mathf.Abs(stamina - 50f) / 50f, 0.1f)) * (armsStaminaDrainMultiplier / 100f);
					stamina = Mathf.Clamp(stamina, 0.01f, 100f);
				}
				if (jointFrameCount.ContainsKey(((Object)((Component)((Joint)joint).connectedBody).gameObject).name.ToLower()))
				{
					jointFrameCount[((Object)((Component)((Joint)joint).connectedBody).gameObject).name.ToLower()] = 0;
				}
			}
			if (num2 < minMovementSpeedToDrainStamina * updateInterval)
			{
				if (((Object)((Joint)joint).connectedBody).name.ToLower().Contains("knee") || ((Object)((Joint)joint).connectedBody).name.ToLower().Contains("hip"))
				{
					stamina += 20f * updateInterval * (legsStaminaRegenMultiplier / 100f);
					stamina = Mathf.Clamp(stamina, 0.01f, 100f);
					playerCardioStamina[name] += 5f * (cardioVascularStaminaRegenMultiplier / 100f) * updateInterval;
					playerCardioStamina[name] = Mathf.Clamp(playerCardioStamina[name], 0.01f, 100f);
				}
				else
				{
					stamina += 20f * updateInterval * (armsStaminaRegenMultiplier / 100f);
					stamina = Mathf.Clamp(stamina, 0.01f, 100f);
					playerCardioStamina[name] += 5f * (cardioVascularStaminaRegenMultiplier / 100f) * updateInterval;
					playerCardioStamina[name] = Mathf.Clamp(playerCardioStamina[name], 0.01f, 100f);
				}
				string key = ((Object)((Component)((Joint)joint).connectedBody).gameObject).name.ToLower();
				if (!jointFrameCount.ContainsKey(key))
				{
					jointFrameCount[key] = 0;
				}
				jointFrameCount[key]++;
				if ((float)jointFrameCount[key] >= 2f / updateInterval)
				{
					stamina = 100f;
					jointFrameCount[key] = 0;
				}
			}
			float num5 = (float)((Component)val2).GetComponent<PlayerHealth>().bloodAmount / 2f;
			num5 = Mathf.Clamp(num5, 0.0001f, 1f);
			JointDrive val4;
			if (originalPositionSprings.TryGetValue(joint, out var value) && originalPositionDampers.TryGetValue(joint, out var value2) && originalMaximumForces.TryGetValue(joint, out var value3))
			{
				if (num5 <= 0.4f)
				{
					val4 = default(JointDrive);
					((JointDrive)(ref val4)).positionSpring = value * ((stamina + stamina + playerCardioStamina[name]) / 3f / 100f) * num5;
					((JointDrive)(ref val4)).positionDamper = value2 * ((stamina + stamina + playerCardioStamina[name]) / 3f / 100f) * num5;
					((JointDrive)(ref val4)).maximumForce = float.MaxValue;
					joint.angularXDrive = val4;
					val4 = default(JointDrive);
					((JointDrive)(ref val4)).positionSpring = value * ((stamina + stamina + playerCardioStamina[name]) / 3f / 100f) * num5;
					((JointDrive)(ref val4)).positionDamper = value2 * ((stamina + stamina + playerCardioStamina[name]) / 3f / 100f) * num5;
					((JointDrive)(ref val4)).maximumForce = float.MaxValue;
					joint.angularYZDrive = val4;
				}
				else
				{
					val4 = default(JointDrive);
					((JointDrive)(ref val4)).positionSpring = value * Mathf.Clamp((stamina + stamina + playerCardioStamina[name]) / 3f / 100f, 0.75f, 1f);
					((JointDrive)(ref val4)).positionDamper = value2;
					((JointDrive)(ref val4)).maximumForce = value3 * ((stamina + stamina + playerCardioStamina[name]) / 3f / 100f);
					joint.angularXDrive = val4;
					val4 = default(JointDrive);
					((JointDrive)(ref val4)).positionSpring = value * Mathf.Clamp((stamina + stamina + playerCardioStamina[name]) / 3f / 100f, 0.75f, 1f);
					((JointDrive)(ref val4)).positionDamper = value2;
					((JointDrive)(ref val4)).maximumForce = value3 * ((stamina + stamina + playerCardioStamina[name]) / 3f / 100f);
					joint.angularYZDrive = val4;
				}
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Original position spring or damper not found for joint " + ((Object)((Component)((Joint)joint).connectedBody).gameObject).name));
			}
			if (num5 <= 0.3f && ((Object)((Component)((Joint)joint).connectedBody).gameObject).name.ToLower().Contains("knee"))
			{
				val4 = default(JointDrive);
				((JointDrive)(ref val4)).positionSpring = 0.1f;
				((JointDrive)(ref val4)).positionDamper = 0.1f;
				((JointDrive)(ref val4)).maximumForce = 0.1f;
				joint.angularXDrive = val4;
				val4 = default(JointDrive);
				((JointDrive)(ref val4)).positionSpring = 0.1f;
				((JointDrive)(ref val4)).positionDamper = 0.1f;
				((JointDrive)(ref val4)).maximumForce = 0.1f;
				joint.angularYZDrive = val4;
			}
		}
	}

	public void UpdateJointValues()
	{
		//IL_0026: 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_004a: 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_0065: 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_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: 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_00e0: 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_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0255: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_027d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: 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_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0312: Unknown result type (might be due to invalid IL or missing references)
		//IL_0317: Unknown result type (might be due to invalid IL or missing references)
		//IL_033a: Unknown result type (might be due to invalid IL or missing references)
		//IL_033f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_035c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0374: Unknown result type (might be due to invalid IL or missing references)
		//IL_0379: Unknown result type (might be due to invalid IL or missing references)
		JointDrive angularXDrive;
		foreach (ConfigurableJoint shoulderJoint in shoulderJoints)
		{
			if ((Object)(object)shoulderJoint != (Object)null)
			{
				angularXDrive = shoulderJoint.angularXDrive;
				if (((JointDrive)(ref angularXDrive)).maximumForce == float.MaxValue)
				{
					Dictionary<ConfigurableJoint, float> dictionary = originalPositionSprings;
					angularXDrive = shoulderJoint.angularXDrive;
					dictionary[shoulderJoint] = ((JointDrive)(ref angularXDrive)).positionSpring;
					Dictionary<ConfigurableJoint, float> dictionary2 = originalPositionDampers;
					angularXDrive = shoulderJoint.angularXDrive;
					dictionary2[shoulderJoint] = ((JointDrive)(ref angularXDrive)).positionDamper;
					Dictionary<ConfigurableJoint, float> dictionary3 = originalMaximumForces;
					angularXDrive = shoulderJoint.angularXDrive;
					dictionary3[shoulderJoint] = ((JointDrive)(ref angularXDrive)).maximumForce;
				}
			}
		}
		foreach (ConfigurableJoint elbowJoint in elbowJoints)
		{
			if ((Object)(object)elbowJoint != (Object)null)
			{
				angularXDrive = elbowJoint.angularXDrive;
				if (((JointDrive)(ref angularXDrive)).maximumForce == float.MaxValue)
				{
					Dictionary<ConfigurableJoint, float> dictionary4 = originalPositionSprings;
					angularXDrive = elbowJoint.angularXDrive;
					dictionary4[elbowJoint] = ((JointDrive)(ref angularXDrive)).positionSpring;
					Dictionary<ConfigurableJoint, float> dictionary5 = originalPositionDampers;
					angularXDrive = elbowJoint.angularXDrive;
					dictionary5[elbowJoint] = ((JointDrive)(ref angularXDrive)).positionDamper;
					Dictionary<ConfigurableJoint, float> dictionary6 = originalMaximumForces;
					angularXDrive = elbowJoint.angularXDrive;
					dictionary6[elbowJoint] = ((JointDrive)(ref angularXDrive)).maximumForce;
				}
			}
		}
		foreach (ConfigurableJoint hipJoint in hipJoints)
		{
			if ((Object)(object)hipJoint != (Object)null)
			{
				angularXDrive = hipJoint.angularXDrive;
				if (((JointDrive)(ref angularXDrive)).maximumForce == float.MaxValue)
				{
					Dictionary<ConfigurableJoint, float> dictionary7 = originalPositionSprings;
					angularXDrive = hipJoint.angularXDrive;
					dictionary7[hipJoint] = ((JointDrive)(ref angularXDrive)).positionSpring;
					Dictionary<ConfigurableJoint, float> dictionary8 = originalPositionDampers;
					angularXDrive = hipJoint.angularXDrive;
					dictionary8[hipJoint] = ((JointDrive)(ref angularXDrive)).positionDamper;
					Dictionary<ConfigurableJoint, float> dictionary9 = originalMaximumForces;
					angularXDrive = hipJoint.angularXDrive;
					dictionary9[hipJoint] = ((JointDrive)(ref angularXDrive)).maximumForce;
				}
			}
		}
		foreach (ConfigurableJoint kneeJoint in kneeJoints)
		{
			if ((Object)(object)kneeJoint != (Object)null)
			{
				angularXDrive = kneeJoint.angularXDrive;
				if (((JointDrive)(ref angularXDrive)).maximumForce == float.MaxValue)
				{
					Dictionary<ConfigurableJoint, float> dictionary10 = originalPositionSprings;
					angularXDrive = kneeJoint.angularXDrive;
					dictionary10[kneeJoint] = ((JointDrive)(ref angularXDrive)).positionSpring;
					Dictionary<ConfigurableJoint, float> dictionary11 = originalPositionDampers;
					angularXDrive = kneeJoint.angularXDrive;
					dictionary11[kneeJoint] = ((JointDrive)(ref angularXDrive)).positionDamper;
					Dictionary<ConfigurableJoint, float> dictionary12 = originalMaximumForces;
					angularXDrive = kneeJoint.angularXDrive;
					dictionary12[kneeJoint] = ((JointDrive)(ref angularXDrive)).maximumForce;
				}
			}
		}
		foreach (ConfigurableJoint spineJoint in spineJoints)
		{
			if ((Object)(object)spineJoint != (Object)null)
			{
				angularXDrive = spineJoint.angularXDrive;
				if (((JointDrive)(ref angularXDrive)).maximumForce == float.MaxValue)
				{
					Dictionary<ConfigurableJoint, float> dictionary13 = originalPositionSprings;
					angularXDrive = spineJoint.angularXDrive;
					dictionary13[spineJoint] = ((JointDrive)(ref angularXDrive)).positionSpring;
					Dictionary<ConfigurableJoint, float> dictionary14 = originalPositionDampers;
					angularXDrive = spineJoint.angularXDrive;
					dictionary14[spineJoint] = ((JointDrive)(ref angularXDrive)).positionDamper;
					Dictionary<ConfigurableJoint, float> dictionary15 = originalMaximumForces;
					angularXDrive = spineJoint.angularXDrive;
					dictionary15[spineJoint] = ((JointDrive)(ref angularXDrive)).maximumForce;
				}
			}
		}
	}

	private void HipStabilizerCalculator(ConfigurableJoint joint, ref Quaternion startingRotation)
	{
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)joint == (Object)null) && !((Object)(object)((Joint)joint).connectedBody == (Object)null) && !((Object)(object)((Component)((Joint)joint).connectedBody).gameObject == (Object)null))
		{
			string name = ((Object)((Component)((Component)((Joint)joint).connectedBody).gameObject.transform.root).gameObject).name;
			List<Transform> list = new List<Transform>();
			Transform val = ((Component)joint).transform;
			while (!((Object)val).name.ToLower().Contains("character"))
			{
				list.Add(val.parent);
				val = val.parent;
			}
			name = ((Object)val).name;
			float num = (float)((Component)val).GetComponent<PlayerHealth>().bloodAmount / 2f;
			num = Mathf.Clamp(num, 0.0001f, 1f);
			if (num <= 0.5f)
			{
				JointDrive val2 = default(JointDrive);
				((JointDrive)(ref val2)).positionSpring = 10000f * hipStabilizerStrengthMultiplier;
				((JointDrive)(ref val2)).positionDamper = 2700f * hipStabilizerDamperMultiplier;
				((JointDrive)(ref val2)).maximumForce = 2500f * (num / 1.2f);
				joint.angularXDrive = val2;
				val2 = default(JointDrive);
				((JointDrive)(ref val2)).positionSpring = 10000f * hipStabilizerStrengthMultiplier;
				((JointDrive)(ref val2)).positionDamper = 2700f * hipStabilizerDamperMultiplier;
				((JointDrive)(ref val2)).maximumForce = 2500f * (num / 1.2f);
				joint.angularYZDrive = val2;
			}
			Vector3 currentTorque = ((Joint)joint).currentTorque;
			float magnitude = ((Vector3)(ref currentTorque)).magnitude;
		}
	}

	private void ChangeFloorPhysicsMaterial()
	{
		GameObject[] array = Object.FindObjectsOfType<GameObject>();
		GameObject[] array2 = array;
		foreach (GameObject val in array2)
		{
			if (!(((Object)val).name.ToLower() == "arenaofblades"))
			{
				continue;
			}
			Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>();
			foreach (Collider val2 in componentsInChildren)
			{
				if (((Object)val2).name.ToLower() == "arenaground.001")
				{
					((BaseUnityPlugin)this).Logger.LogError((object)(((Object)val2).name ?? ""));
					val2.material = floorPhyMaterial;
					val2.material.staticFriction = floorFriction / 100f;
					val2.material.dynamicFriction = floorFriction / 100f;
					if (floorFriction > 60f)
					{
						val2.material.frictionCombine = (PhysicMaterialCombine)3;
					}
					if (floorFriction < 60f)
					{
						val2.material.frictionCombine = (PhysicMaterialCombine)2;
					}
				}
			}
		}
	}

	private void ToggleMenu()
	{
		showMenu = !showMenu;
	}

	private void OnGUI()
	{
		//IL_0027: 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_007b: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: 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_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Unknown result type (might be due to invalid IL or missing references)
		//IL_027d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_032f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0367: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0419: Unknown result type (might be due to invalid IL or missing references)
		//IL_0451: Unknown result type (might be due to invalid IL or missing references)
		//IL_048e: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0503: Unknown result type (might be due to invalid IL or missing references)
		//IL_053b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0578: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_0625: Unknown result type (might be due to invalid IL or missing references)
		//IL_0662: Unknown result type (might be due to invalid IL or missing references)
		if (showMenu)
		{
			GUI.Box(new Rect(10f, 10f, 420f, 620f), "ImprovedCharacterPhysics Menu");
			useMod = GUI.Toggle(new Rect(20f, 40f, 230f, 20f), useMod, "Use Mod");
			useCustomHipStabilizer = GUI.Toggle(new Rect(20f, 70f, 230f, 20f), useCustomHipStabilizer, "Use Custom Hip Stabilizer");
			GUI.Label(new Rect(20f, 100f, 400f, 20f), "Hip Stabilizer Strength (Anti-Torque Exploit): " + Mathf.RoundToInt(hipStabilizerStrengthMultiplier));
			hipStabilizerStrengthMultiplier = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 120f, 400f, 20f), hipStabilizerStrengthMultiplier, 0f, 200f));
			GUI.Label(new Rect(20f, 140f, 400f, 20f), "Hip Stabilizer Damper: " + Mathf.RoundToInt(hipStabilizerDamperMultiplier));
			hipStabilizerDamperMultiplier = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 160f, 400f, 20f), hipStabilizerDamperMultiplier, 0f, 200f));
			GUI.Label(new Rect(20f, 180f, 400f, 20f), "Arm Strength: " + Mathf.RoundToInt(armStrenghtMultiplier));
			armStrenghtMultiplier = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 200f, 400f, 20f), armStrenghtMultiplier, 0f, 200f));
			GUI.Label(new Rect(20f, 220f, 400f, 20f), "Leg Strength: " + Mathf.RoundToInt(legStrengthMultiplier));
			legStrengthMultiplier = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 240f, 400f, 20f), legStrengthMultiplier, 0f, 200f));
			GUI.Label(new Rect(20f, 260f, 400f, 20f), "Spine Strength: " + Mathf.RoundToInt(spineStrenghtMultiplier));
			spineStrenghtMultiplier = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 280f, 400f, 20f), spineStrenghtMultiplier, 0f, 200f));
			GUI.Label(new Rect(20f, 300f, 400f, 20f), "min Movement Speed to Drain Stamina (Degrees per second): " + Mathf.RoundToInt(minMovementSpeedToDrainStamina));
			minMovementSpeedToDrainStamina = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 320f, 400f, 20f), minMovementSpeedToDrainStamina, 0f, 200f));
			GUI.Label(new Rect(20f, 340f, 400f, 20f), "Arms Stamina Drain: " + Mathf.RoundToInt(armsStaminaDrainMultiplier));
			armsStaminaDrainMultiplier = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 360f, 400f, 20f), armsStaminaDrainMultiplier, 0f, 200f));
			GUI.Label(new Rect(20f, 380f, 400f, 20f), "Arms Stamina Regen: " + Mathf.RoundToInt(armsStaminaRegenMultiplier));
			armsStaminaRegenMultiplier = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 400f, 400f, 20f), armsStaminaRegenMultiplier, 0f, 200f));
			GUI.Label(new Rect(20f, 420f, 400f, 20f), "Legs Stamina Drain: " + Mathf.RoundToInt(legsStaminaDrainMultiplier));
			legsStaminaDrainMultiplier = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 440f, 400f, 20f), legsStaminaDrainMultiplier, 0f, 200f));
			GUI.Label(new Rect(20f, 460f, 400f, 20f), "Legs Stamina Regen: " + Mathf.RoundToInt(legsStaminaRegenMultiplier));
			legsStaminaRegenMultiplier = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 480f, 400f, 20f), legsStaminaRegenMultiplier, 0f, 200f));
			GUI.Label(new Rect(20f, 500f, 400f, 20f), "Cardiovascular/Shared Stamina Drain: " + Mathf.RoundToInt(cardioVascularStaminaDrainMultiplier));
			cardioVascularStaminaDrainMultiplier = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 520f, 400f, 20f), cardioVascularStaminaDrainMultiplier, 0f, 200f));
			GUI.Label(new Rect(20f, 540f, 400f, 20f), "Cardiovascular/Shared Stamina Regen: " + Mathf.RoundToInt(cardioVascularStaminaRegenMultiplier));
			cardioVascularStaminaRegenMultiplier = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 560f, 400f, 20f), cardioVascularStaminaRegenMultiplier, 0f, 200f));
			GUI.Label(new Rect(20f, 580f, 400f, 20f), "Floor Friction: " + Mathf.RoundToInt(floorFriction));
			floorFriction = Mathf.Round(GUI.HorizontalSlider(new Rect(20f, 600f, 400f, 20f), floorFriction, 1f, 100f));
		}
	}
}
[HarmonyPatch(typeof(JointStrength), "DealMuscleDamage")]
public class JointStrengthPatch
{
	private static void Postfix(JointStrength __instance)
	{
		ImprovedCharacterPhysics component = Chainloader.ManagerObject.GetComponent<ImprovedCharacterPhysics>();
		if ((Object)(object)component != (Object)null)
		{
			component.UpdateJointValues();
		}
		else
		{
			Debug.LogError((object)"ImprovedCharacterPhysics instance not found!");
		}
	}
}