Decompiled source of StableCamera v1.4.0

StableCamera.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MonoMod.Utils;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Rendering;
using Zorro.Settings;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("linkoid")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0+f4a6b85cc8e5578eead64c772eafab4d95ea6f4f")]
[assembly: AssemblyProduct("StableCamera")]
[assembly: AssemblyTitle("StableCamera")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	internal static class IsExternalInit
	{
	}
}
namespace Linkoid.Peak.StableCamera
{
	[HarmonyPatch(typeof(MainCameraMovement))]
	public class BodypartStableData : MonoBehaviour
	{
		[SerializeField]
		private Bodypart bodypart;

		[SerializeField]
		internal Vector3 targetOffsetRelativeToCenterOfMass;

		[SerializeField]
		private Vector3 previousTargetOffset;

		[SerializeField]
		private Vector3 previousTargetForward;

		[SerializeField]
		private Vector3 previousTargetUp;

		private void Awake()
		{
			//IL_0013: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_003a: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			bodypart = ((Component)this).GetComponent<Bodypart>();
			targetOffsetRelativeToCenterOfMass = bodypart.targetOffsetRelativeToHip * 0.75f;
			previousTargetOffset = targetOffsetRelativeToCenterOfMass;
			previousTargetForward = bodypart.targetForward;
			previousTargetUp = bodypart.targetUp;
		}

		public Vector3 InterpolatedTargetOffsetRelativeToCenterOfMass()
		{
			//IL_0001: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.LerpUnclamped(previousTargetOffset, targetOffsetRelativeToCenterOfMass, (Time.time - Time.fixedTime) / Time.fixedDeltaTime);
		}

		public Vector3 InterpolatedTargetForward()
		{
			//IL_0001: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SlerpUnclamped(previousTargetForward, bodypart.targetForward, (Time.time - Time.fixedTime) / Time.fixedDeltaTime);
		}

		public Vector3 InterpolatedTargetUp()
		{
			//IL_0001: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.SlerpUnclamped(previousTargetUp, bodypart.targetUp, (Time.time - Time.fixedTime) / Time.fixedDeltaTime);
		}

		public void SaveStableData()
		{
			//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_0013: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_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)
			previousTargetOffset = targetOffsetRelativeToCenterOfMass;
			previousTargetForward = bodypart.targetForward;
			previousTargetUp = bodypart.targetUp;
			targetOffsetRelativeToCenterOfMass = bodypart.WorldCenterOfMass() - bodypart.character.refs.ragdoll.WorldCenterOfMass();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Bodypart), "SaveAnimationData")]
		private static void SaveAnimationData_Prefix(Bodypart __instance)
		{
			BodypartStableData bodypartStableData = default(BodypartStableData);
			if (((Component)__instance).TryGetComponent<BodypartStableData>(ref bodypartStableData))
			{
				bodypartStableData.SaveStableData();
			}
		}
	}
	[HarmonyPatch]
	internal static class CharacterDataExtensions
	{
		private static Func<CharacterData, float>? get_currentRagdollControll;

		[HarmonyPrepare]
		private static void GetDynamicMethods(Harmony harmony)
		{
			try
			{
				ReversePatch_GetCurrentRagdollControll(harmony);
			}
			catch (Exception ex)
			{
				StableCamera.Logger.LogError((object)ex);
				StableCamera.QueueLogMessage("<leftColor>An minor error has occured in <userColor>StableCamera</color>. The mod may not work as expected.</color>", sfxJoin: false, sfxLeave: true, 5f);
			}
		}

		private static void ReversePatch_GetCurrentRagdollControll(Harmony harmony)
		{
			MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(CharacterData), "currentRagdollControll");
			if ((object)methodInfo != null)
			{
				get_currentRagdollControll = Extensions.CreateDelegate<Func<CharacterData, float>>((MethodBase)methodInfo);
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(CharacterData), "currentRagdollControll");
			if ((object)fieldInfo != null)
			{
				get_currentRagdollControll = CompileFieldGetter<CharacterData, float>(fieldInfo);
				return;
			}
			throw new MissingMemberException("Field or property 'CharacterData.currentRagdollControll' not found.");
		}

		public static float GetCurrentRagdollControll(this CharacterData characterData)
		{
			return get_currentRagdollControll?.Invoke(characterData) ?? 1f;
		}

		[return: NotNullIfNotNull("fieldInfo")]
		private static Func<TTarget, TResult>? CompileFieldGetter<TTarget, TResult>(FieldInfo? fieldInfo)
		{
			ParameterExpression parameterExpression = Expression.Parameter(typeof(TTarget), "obj");
			MemberExpression body = Expression.Field(parameterExpression, fieldInfo);
			return Expression.Lambda<Func<TTarget, TResult>>(body, new ParameterExpression[1] { parameterExpression }).Compile();
		}
	}
	internal static class ConfigFileExtensions
	{
		private static readonly MethodInfo prop_OrphanedEntries = AccessTools.DeclaredPropertyGetter(typeof(ConfigFile), "OrphanedEntries");

		public static IReadOnlyCollection<ConfigDefinition> GetOrphanedDefinitions(this ConfigFile configFile)
		{
			Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)prop_OrphanedEntries.Invoke(configFile, Array.Empty<object>());
			return dictionary.Keys;
		}

		public static bool TryGetOrphanedEntry<T>(this ConfigFile configFile, ConfigDefinition configDefinition, [NotNullWhen(true)] out ConfigEntry<T>? entry, T defaultValue = default(T), ConfigDescription? configDescription = null)
		{
			entry = null;
			if (!configFile.GetOrphanedDefinitions().Contains(configDefinition))
			{
				return false;
			}
			entry = configFile.Bind<T>(configDefinition, defaultValue, configDescription);
			return true;
		}

		public static bool TryGetOrphanedEntry<T>(this ConfigFile configFile, string section, string key, [NotNullWhen(true)] out ConfigEntry<T>? entry, T defaultValue = default(T), ConfigDescription? configDescription = null)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			return configFile.TryGetOrphanedEntry(new ConfigDefinition(section, key), out entry, defaultValue, configDescription);
		}

		public static bool TryGetOrphanedEntry<T>(this ConfigFile configFile, string section, string key, [NotNullWhen(true)] out ConfigEntry<T>? entry, T defaultValue, string description)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_001d: Expected O, but got Unknown
			return configFile.TryGetOrphanedEntry(new ConfigDefinition(section, key), out entry, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}
	}
	internal readonly record struct ConfigModel(ConfigFile ConfigFile)
	{
		public readonly ConfigEntry<bool> Enabled = ConfigFile.Bind<bool>("StableCamera", "Enabled", true, "Enables the mod. Setting this to false effectively disables the entire mod.");

		public readonly ConfigEntry<KeyCode> ToggleKey = ConfigFile.Bind<KeyCode>("StableCamera", "ToggleKey", (KeyCode)110, "The shortcut key which toggles the mod on or off in-game.");

		public readonly ConfigEntry<bool> StabilizeTracking = ConfigFile.Bind<bool>("StableCamera", "StabilizeTracking", true, "Reduce camera wobble using stabilized tracking. Disable this if head clipping is more annoying than wobble.");

		public readonly ConfigEntry<float> TrackingPower = ConfigFile.Bind<float>("StableCamera", "TrackingPower", 2f, new ConfigDescription("How aggressively the camera will follow the character. Higher values lead to more wobble, but less clipping.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 400f), Array.Empty<object>()));

		public readonly ConfigEntry<bool> HideFullBody = ConfigFile.Bind<bool>("StableCamera", "HideFullBody", false, "Hide the entire body. Will cause arms to be invisible in first person, but when TrackingPower is less than 1, this will prevent the body from blocking the view.");

		public readonly ConfigEntry<bool> ThirdPersonRagdoll = ConfigFile.Bind<bool>("StableCamera", "ThirdPersonRagdoll", true, "Switch to a third-person camera whenever the character ragdolls.");

		public readonly ConfigEntry<float> ExtraClimbingFOV = ConfigFile.Bind<float>("StableCamera", "ExtraClimbingFOV", 0f, new ConfigDescription("How much the camera's field of view expands while climbing. A value of 0 prevents the FOV from changing; 40 is the game's original value.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 70f), Array.Empty<object>()));

		public readonly ConfigEntry<float> DizzyEffectStrength = ConfigFile.Bind<float>("StableCamera", "DizzyEffectStrength", 0f, new ConfigDescription("Strength factor of the dizzy camera effect, e.g. when recovering from passing out.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));

		public readonly ConfigEntry<float> ShakeEffectStrength = ConfigFile.Bind<float>("StableCamera", "ShakeEffectStrength", 0f, new ConfigDescription("Strength factor of the camera shake effect, e.g. when stamina is exhausted while climbing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));

		public void RunMigrations()
		{
			ConfigFile.SaveOnConfigSet = false;
			try
			{
				Migrate_1_1();
				ConfigFile.Save();
			}
			catch (Exception ex)
			{
				StableCamera.Logger.LogWarning((object)("An error occured during config migration. Please delete the config file.\n" + ex.Message + "\n" + ex.StackTrace));
			}
			ConfigFile.SaveOnConfigSet = true;
		}

		private bool Migrate_1_1()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			bool flag = false;
			if (!(flag | ConfigFile.TryGetOrphanedEntry(new ConfigDefinition("StableCamera", "StabilizeCamera"), out ConfigEntry<bool> entry, defaultValue: false)))
			{
				return false;
			}
			StableCamera.Logger.LogMessage((object)"Migrating config from v1.0 to v1.1");
			if (entry != null)
			{
				Enabled.Value = entry.Value;
			}
			ConfigFile.Remove((entry != null) ? ((ConfigEntryBase)entry).Definition : null);
			return true;
		}
	}
	[HarmonyPatch]
	[RequireComponent(typeof(Camera), typeof(MainCameraMovement))]
	internal class MainCameraBodyHider : MonoBehaviour
	{
		private static readonly List<Renderer> reusableRendererList = new List<Renderer>();

		private Camera camera;

		private MainCameraMovement mainCameraMovement;

		private HideTheBody playerBodyHider;

		public static MainCameraBodyHider Instance { get; private set; }

		[HarmonyPostfix]
		[HarmonyPatch(typeof(MainCameraMovement), "Start")]
		private static void CreateMainCameraBodyHider(MainCameraMovement __instance)
		{
			((Component)__instance).gameObject.AddComponent<MainCameraBodyHider>();
		}

		private void Awake()
		{
			Instance = this;
			camera = ((Component)this).GetComponent<Camera>();
			mainCameraMovement = ((Component)this).GetComponent<MainCameraMovement>();
		}

		private void OnEnable()
		{
			RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
		}

		private void OnDisable()
		{
			RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
			if (TryGetPlayerBodyHider())
			{
				EnableHeadAndHats(enabled: true);
				EnableBodyAndCostumes(enabled: true);
			}
		}

		private void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
		{
			if (TryGetPlayerBodyHider())
			{
				if ((Object)(object)camera == (Object)(object)this.camera)
				{
					ConditionallyDisableMeshRenderers();
					return;
				}
				EnableHeadAndHats(enabled: true);
				EnableBodyAndCostumes(enabled: true);
			}
		}

		private bool TryGetPlayerBodyHider()
		{
			if ((Object)(object)playerBodyHider != (Object)null)
			{
				return true;
			}
			if ((Object)(object)Character.localCharacter == (Object)null)
			{
				return false;
			}
			playerBodyHider = ((Component)Character.localCharacter).GetComponentInChildren<HideTheBody>();
			return (Object)(object)playerBodyHider != (Object)null;
		}

		private void ConditionallyDisableMeshRenderers()
		{
			CharacterData val = Character.localCharacter?.data;
			bool flag = false;
			if ((Object)(object)val != (Object)null)
			{
				flag = (StableCamera.Config.ThirdPersonRagdoll.Value && mainCameraMovement.ragdollCam > 0.35f) || val.passedOut || val.fullyPassedOut || val.dead;
			}
			bool flag2 = StableCamera.Config.Enabled.Value && !flag;
			bool flag3 = flag2 && StableCamera.Config.HideFullBody.Value;
			EnableHeadAndHats(!flag2);
			EnableBodyAndCostumes(!flag3);
		}

		private void EnableHeadAndHats(bool enabled)
		{
			playerBodyHider.headRend.enabled = enabled;
			Renderer[] playerHats = playerBodyHider.refs.playerHats;
			foreach (Renderer val in playerHats)
			{
				val.enabled = enabled;
			}
			((Component)playerBodyHider.face).GetComponentsInChildren<Renderer>(reusableRendererList);
			foreach (Renderer reusableRenderer in reusableRendererList)
			{
				reusableRenderer.enabled = enabled;
			}
		}

		private void EnableBodyAndCostumes(bool enabled)
		{
			((Renderer)playerBodyHider.body).enabled = enabled;
			((Renderer)playerBodyHider.sash).enabled = enabled;
			SkinnedMeshRenderer[] costumes = playerBodyHider.costumes;
			foreach (SkinnedMeshRenderer val in costumes)
			{
				((Renderer)val).enabled = enabled;
			}
		}
	}
	[HarmonyPatch(typeof(MainCameraMovement))]
	internal static class MainCameraMovementPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("CharacterCam")]
		private static bool CharacterCam_Prefix(MainCameraMovement __instance)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: 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_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: 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_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_0299: 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_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: 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)
			if (!StableCamera.Config.Enabled.Value)
			{
				return true;
			}
			if ((Object)(object)Character.localCharacter == (Object)null)
			{
				return true;
			}
			__instance.cam.cam.fieldOfView = __instance.GetFov();
			if ((Object)(object)Character.localCharacter == (Object)null || (Object)(object)Character.localCharacter == (Object)null)
			{
				return true;
			}
			if (Character.localCharacter.data.lookDirection != Vector3.zero)
			{
				((Component)__instance).transform.rotation = Quaternion.LookRotation(Character.localCharacter.data.lookDirection);
				float num = 1f - Character.localCharacter.data.GetCurrentRagdollControll();
				if (num > __instance.ragdollCam)
				{
					__instance.ragdollCam = Mathf.Lerp(__instance.ragdollCam, num, Time.deltaTime * 5f);
				}
				else
				{
					__instance.ragdollCam = Mathf.Lerp(__instance.ragdollCam, num, Time.deltaTime * 0.5f);
				}
				__instance.physicsRot = Quaternion.Lerp(__instance.physicsRot, ((Component)Character.localCharacter.GetBodypartRig((BodypartType)4)).transform.rotation, Time.deltaTime * 10f);
				if (!StableCamera.Config.ThirdPersonRagdoll.Value)
				{
					((Component)__instance).transform.rotation = Quaternion.Lerp(((Component)__instance).transform.rotation, __instance.physicsRot, __instance.ragdollCam * StableCamera.Config.DizzyEffectStrength.Value);
				}
				Quaternion val = Quaternion.Euler(GamefeelHandler.instance.GetRotation());
				Transform transform = ((Component)__instance).transform;
				Quaternion val2 = Quaternion.Slerp(Quaternion.identity, val, StableCamera.Config.ShakeEffectStrength.Value);
				transform.Rotate(((Quaternion)(ref val2)).eulerAngles, (Space)0);
			}
			Vector3 cameraPos = Character.localCharacter.GetCameraPos(__instance.GetHeadOffset());
			Vector3 ragdollCameraPosition = GetRagdollCameraPosition(__instance);
			__instance.targetPlayerPovPosition = Vector3.Lerp(cameraPos, ragdollCameraPosition, __instance.ragdollCam);
			float num2 = Vector3.Distance(((Component)__instance).transform.position, __instance.targetPlayerPovPosition);
			if (num2 > __instance.characterPovMaxDistance)
			{
				Vector3 targetPlayerPovPosition = __instance.targetPlayerPovPosition;
				Vector3 val3 = ((Component)__instance).transform.position - __instance.targetPlayerPovPosition;
				Vector3 val4 = targetPlayerPovPosition + ((Vector3)(ref val3)).normalized * __instance.characterPovMaxDistance;
				if (StableCamera.Config.StabilizeTracking.Value)
				{
					((Component)__instance).transform.position = Vector3.Lerp(((Component)__instance).transform.position, val4, Time.deltaTime * (__instance.characterPovLerpRate + num2 / __instance.characterPovMaxDistance * StableCamera.Config.TrackingPower.Value));
				}
				else
				{
					((Component)__instance).transform.position = val4;
				}
			}
			((Component)__instance).transform.position = Vector3.Lerp(((Component)__instance).transform.position, __instance.targetPlayerPovPosition, Time.deltaTime * __instance.characterPovLerpRate);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetFov")]
		private static bool GetFov_Prefix(MainCameraMovement __instance, ref float __result)
		{
			if (!StableCamera.Config.Enabled.Value)
			{
				return true;
			}
			if ((Object)(object)Character.localCharacter == (Object)null)
			{
				return true;
			}
			float num = ((FloatSetting)__instance.fovSetting).Value;
			if (num < 60f)
			{
				num = 70f;
			}
			__instance.currentFov = Mathf.Lerp(__instance.currentFov, num + (Character.localCharacter.data.isClimbing ? StableCamera.Config.ExtraClimbingFOV.Value : 0f), Time.deltaTime * 5f);
			__result = __instance.currentFov;
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Character), "GetCameraPos")]
		private static void GetCameraPos_Postfix(Character __instance, ref Vector3 __result, float forwardOffset)
		{
			//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_0042: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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_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_00a8: Unknown result type (might be due to invalid IL or missing references)
			if (StableCamera.Config.Enabled.Value && StableCamera.Config.StabilizeTracking.Value)
			{
				Vector3 cameraAnchor = GetCameraAnchor(__instance, forwardOffset);
				float num = MainCamera.instance.cam.nearClipPlane * 1.7320508f;
				Vector3 val = cameraAnchor - __result;
				float magnitude = ((Vector3)(ref val)).magnitude;
				Vector3 val2 = val / magnitude;
				RaycastHit val3 = default(RaycastHit);
				if (Physics.SphereCast(__result, num, val2, ref val3, magnitude, LayerMask.GetMask(new string[2] { "Terrain", "Map" })))
				{
					__result += val2 * ((RaycastHit)(ref val3)).distance;
				}
				else
				{
					__result = cameraAnchor;
				}
			}
		}

		private static Vector3 GetCameraAnchor(Character character, float forwardOffset)
		{
			//IL_0024: 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_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_003b: 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_0046: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_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)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			Bodypart bodypart = character.GetBodypart((BodypartType)4);
			BodypartStableData bodypartStableData = default(BodypartStableData);
			if (!((Component)bodypart).TryGetComponent<BodypartStableData>(ref bodypartStableData))
			{
				bodypartStableData = ((Component)bodypart).gameObject.AddComponent<BodypartStableData>();
			}
			Vector3 val = Vector3.Scale(((Component)bodypart).transform.lossyScale, bodypartStableData.InterpolatedTargetUp());
			Vector3 val2 = Vector3.Scale(((Component)bodypart).transform.lossyScale, bodypartStableData.InterpolatedTargetForward());
			Vector3 val3 = val + val2 * forwardOffset;
			Vector3 val4 = bodypartStableData.InterpolatedTargetOffsetRelativeToCenterOfMass();
			return character.refs.ragdoll.WorldCenterOfMass() + val4 + val3;
		}

		private static Vector3 GetCameraAnchor_EXPERIMENTAL(Character character, float forwardOffset)
		{
			//IL_001b: 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_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_0040: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_0064: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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)
			Bodypart bodypart = character.GetBodypart((BodypartType)4);
			Bodypart bodypart2 = character.GetBodypart((BodypartType)0);
			PlayableGraph playableGraph = character.refs.animator.playableGraph;
			((PlayableGraph)(ref playableGraph)).Evaluate();
			Vector3 val = character.refs.ragdoll.WorldCenterOfMass();
			Vector3 val2 = ((Component)bodypart).transform.TransformPoint(Vector3.up * 1f + Vector3.forward * forwardOffset);
			Vector3 val3 = val2 - val;
			foreach (Bodypart part in character.refs.ragdoll.partList)
			{
				part.ResetTransform();
			}
			Vector3 val4 = character.refs.ragdoll.WorldCenterOfMass();
			return val4 + val3;
		}

		private static Vector3 GetRagdollCameraPosition(MainCameraMovement __instance)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_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_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)
			//IL_0079: 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_007f: 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_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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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)
			Transform transform = ((Component)Character.localCharacter.GetBodypart((BodypartType)2)).transform;
			if (!StableCamera.Config.ThirdPersonRagdoll.Value)
			{
				return transform.position;
			}
			Vector3 val = Character.localCharacter.data.lookDirection;
			if (val == Vector3.zero)
			{
				val = ((Component)__instance).transform.forward;
			}
			val = ((Vector3)(ref val)).normalized;
			float num = 3f * __instance.ragdollCam * __instance.ragdollCam;
			Vector3 cameraAnchor = GetCameraAnchor(Character.localCharacter, __instance.GetHeadOffset());
			return cameraAnchor - val * num;
		}
	}
	internal static class RagdollExtensions
	{
		public static Vector3 WorldCenterOfMass(this CharacterRagdoll ragdoll)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_004e: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.zero;
			float num = 0f;
			foreach (Bodypart part in ragdoll.partList)
			{
				Rigidbody rig = part.Rig;
				val += ((Component)part).transform.TransformPoint(rig.centerOfMass) * rig.mass;
				num += rig.mass;
			}
			return val / num;
		}
	}
	[BepInPlugin("Linkoid.Peak.StableCamera", "StableCamera", "1.4")]
	public class StableCamera : BaseUnityPlugin
	{
		internal static StableCamera Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		internal static ConfigModel Config { get; private set; }

		private void Awake()
		{
			Instance = this;
			Config = new ConfigModel(((BaseUnityPlugin)this).Config);
			Config.RunMigrations();
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		internal void Patch()
		{
			//IL_0019: 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: Expected O, but got Unknown
			//IL_0025: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(Config.ToggleKey.Value))
			{
				Config.Enabled.Value = !Config.Enabled.Value;
				OnToggleEnabled(Config.Enabled.Value);
			}
		}

		private void OnToggleEnabled(bool enabled)
		{
			Logger.LogInfo((object)$"Stable Camera Enabled: {Config.Enabled.Value}");
			QueueLogMessage("<userColor>Stable Camera</color> has been " + (enabled ? "<joinedColor>" : "<leftColor>") + (enabled ? "enabled" : "disabled") + "</color>");
		}

		public static void QueueLogMessage(string message, bool sfxJoin = false, bool sfxLeave = false, float delay = -1f)
		{
			((MonoBehaviour)Instance).StartCoroutine(Instance.QueueLogMessageRoutine(message, sfxJoin, sfxLeave, delay));
		}

		private IEnumerator QueueLogMessageRoutine(string message, bool sfxJoin = false, bool sfxLeave = false, float delay = -1f)
		{
			PlayerConnectionLog log;
			while (true)
			{
				PlayerConnectionLog val;
				log = (val = Object.FindObjectOfType<PlayerConnectionLog>());
				if (val != null)
				{
					break;
				}
				yield return null;
			}
			if (delay >= 0f)
			{
				yield return (object)new WaitForSeconds(delay);
			}
			message = message.Replace("<userColor>", log.GetColorTag(log.userColor));
			message = message.Replace("<joinedColor>", log.GetColorTag(log.joinedColor));
			message = message.Replace("<leftColor>", log.GetColorTag(log.leftColor));
			log.AddMessage(message);
			if (sfxJoin)
			{
				SFX_Instance sfxJoin2 = log.sfxJoin;
				if (sfxJoin2 != null)
				{
					sfxJoin2.Play(default(Vector3));
				}
			}
			if (sfxLeave)
			{
				SFX_Instance sfxLeave2 = log.sfxLeave;
				if (sfxLeave2 != null)
				{
					sfxLeave2.Play(default(Vector3));
				}
			}
		}
	}
}