Decompiled source of ShoulderCam v1.0.0

BepInEx/plugins/ShoulderCam/ShoulderCam.dll

Decompiled 3 weeks ago
using System;
using System.Diagnostics;
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 UnityEngine;
using UnityEngine.InputSystem;
using Zorro.Settings;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShoulderCam")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ShoulderCam")]
[assembly: AssemblyTitle("Shoulder Camera")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 ShoulderCam
{
	[HarmonyPatch(typeof(CharacterClimbing), "TryToStartWallClimb")]
	internal static class ClimbCameraPatch
	{
		[HarmonyPrefix]
		private static void Prefix(CharacterClimbing __instance, ref float raycastDistance)
		{
			//IL_0075: 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 (!ShoulderCamPlugin.Cfg.Enabled.Value || !ShoulderCamera.ThirdPersonActive)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if (!((Object)(object)localCharacter == (Object)null) && localCharacter.refs != null && !((Object)(object)localCharacter.refs.head == (Object)null) && !((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponent<Character>() != (Object)(object)localCharacter))
			{
				MainCamera instance = MainCamera.instance;
				if (!((Object)(object)instance == (Object)null))
				{
					raycastDistance += Vector3.Distance(((Component)instance).transform.position, localCharacter.refs.head.transform.position);
				}
			}
		}
	}
	[HarmonyPatch(typeof(CharacterItems), "UpdateClimbingSpikeUse")]
	internal static class ClimbSpikeRangePatch
	{
		private static readonly FieldInfo SpikeField = AccessTools.Field(typeof(CharacterItems), "currentClimbingSpikeComponent");

		private static ClimbingSpikeComponent _spike;

		private static float _startDistance;

		private static float _startDistanceGrounded;

		private static float _previewDistance;

		private static float _previewDistanceGrounded;

		private static bool _changed;

		[HarmonyPrefix]
		private static void Prefix(CharacterItems __instance)
		{
			_changed = false;
			if (!ShoulderCamPlugin.Cfg.Enabled.Value || !ShoulderCamera.ThirdPersonActive)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || (Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).GetComponent<Character>() != (Object)(object)localCharacter)
			{
				return;
			}
			ClimbingSpikeComponent val = (ClimbingSpikeComponent)((SpikeField == null) ? null : /*isinst with value type is only supported in some contexts*/);
			if (!((Object)(object)val == (Object)null))
			{
				float num = ShoulderCamera.CameraToHeadDistance(localCharacter);
				if (!(num <= 0.01f))
				{
					_spike = val;
					_startDistance = val.climbingSpikeStartDistance;
					_startDistanceGrounded = val.climbingSpikeStartDistanceGrounded;
					_previewDistance = val.climbingSpikePreviewDisableDistance;
					_previewDistanceGrounded = val.climbingSpikePreviewDisableDistanceGrounded;
					val.climbingSpikeStartDistance = _startDistance + num;
					val.climbingSpikeStartDistanceGrounded = _startDistanceGrounded + num;
					val.climbingSpikePreviewDisableDistance = _previewDistance + num;
					val.climbingSpikePreviewDisableDistanceGrounded = _previewDistanceGrounded + num;
					_changed = true;
				}
			}
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			if (_changed)
			{
				_changed = false;
				if (!((Object)(object)_spike == (Object)null))
				{
					_spike.climbingSpikeStartDistance = _startDistance;
					_spike.climbingSpikeStartDistanceGrounded = _startDistanceGrounded;
					_spike.climbingSpikePreviewDisableDistance = _previewDistance;
					_spike.climbingSpikePreviewDisableDistanceGrounded = _previewDistanceGrounded;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Constructable), "Update")]
	internal static class ConstructableRangePatch
	{
		private static Constructable _constructable;

		private static float _baseDistance;

		private static bool _changed;

		[HarmonyPrefix]
		private static void Prefix(Constructable __instance)
		{
			_changed = false;
			if (!ShoulderCamPlugin.Cfg.Enabled.Value || !ShoulderCamera.ThirdPersonActive)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if (!((Object)(object)localCharacter == (Object)null) && !((Object)(object)__instance == (Object)null) && !((Object)(object)((ItemComponent)__instance).holderCharacter != (Object)(object)localCharacter))
			{
				float num = ShoulderCamera.CameraToHeadDistance(localCharacter);
				if (!(num <= 0.01f))
				{
					_constructable = __instance;
					_baseDistance = __instance.maxConstructDistance;
					__instance.maxConstructDistance = _baseDistance + num;
					_changed = true;
				}
			}
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			if (_changed)
			{
				_changed = false;
				if ((Object)(object)_constructable != (Object)null)
				{
					_constructable.maxConstructDistance = _baseDistance;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Interaction), "DoInteractableRaycasts")]
	internal static class InteractionRangePatch
	{
		private static Interaction _instance;

		private static int _instanceId = int.MinValue;

		private static float _baseDistance;

		private static float _baseArea;

		private static bool _changed;

		[HarmonyPrefix]
		private static void Prefix(Interaction __instance)
		{
			_changed = false;
			if (!ShoulderCamPlugin.Cfg.Enabled.Value || !ShoulderCamera.ThirdPersonActive)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			float num = ShoulderCamera.CameraToHeadDistance(localCharacter);
			if (!(num <= 0.01f))
			{
				int instanceID = ((Object)__instance).GetInstanceID();
				if (_instanceId != instanceID)
				{
					_instanceId = instanceID;
					_baseDistance = __instance.distance;
					_baseArea = __instance.area;
				}
				_instance = __instance;
				__instance.distance = _baseDistance + num + ShoulderCamPlugin.Cfg.ThirdPersonGrabRangeBonus.Value;
				__instance.area = ShoulderCamPlugin.Cfg.ThirdPersonGrabRadius.Value;
				_changed = true;
			}
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			if (_changed && !((Object)(object)_instance == (Object)null))
			{
				_changed = false;
				_instance.distance = _baseDistance;
				_instance.area = _baseArea;
			}
		}
	}
	[HarmonyPatch(typeof(MainCameraMovement), "LateUpdate")]
	internal static class MainCameraPatch
	{
		[HarmonyPostfix]
		private static void Postfix(MainCameraMovement __instance)
		{
			ShoulderCamera.Apply(__instance);
		}
	}
	internal sealed class ModConfig
	{
		public readonly ConfigEntry<bool> Enabled;

		public readonly ConfigEntry<bool> ThirdPersonByDefault;

		public readonly ConfigEntry<bool> StartOnLeftShoulder;

		public readonly ConfigEntry<KeyCode> ToggleViewKey;

		public readonly ConfigEntry<KeyCode> SwapShoulderKey;

		public readonly ConfigEntry<float> OrbitHoldSeconds;

		public readonly ConfigEntry<float> Distance;

		public readonly ConfigEntry<float> NearDistance;

		public readonly ConfigEntry<float> FarDistance;

		public readonly ConfigEntry<float> ShoulderOffset;

		public readonly ConfigEntry<float> HeightOffset;

		public readonly ConfigEntry<float> TransitionSeconds;

		public readonly ConfigEntry<float> PositionSharpness;

		public readonly ConfigEntry<float> RotationSharpness;

		public readonly ConfigEntry<float> ShoulderSwapSharpness;

		public readonly ConfigEntry<float> CollisionRadius;

		public readonly ConfigEntry<float> ThirdPersonFovBonus;

		public readonly ConfigEntry<bool> ShowBody;

		public readonly ConfigEntry<float> ThirdPersonGrabRadius;

		public readonly ConfigEntry<float> ThirdPersonGrabRangeBonus;

		public ModConfig(ConfigFile cfg)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Expected O, but got Unknown
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Expected O, but got Unknown
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Expected O, but got Unknown
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Expected O, but got Unknown
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Expected O, but got Unknown
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Expected O, but got Unknown
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Expected O, but got Unknown
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Expected O, but got Unknown
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Expected O, but got Unknown
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Expected O, but got Unknown
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Expected O, but got Unknown
			Enabled = cfg.Bind<bool>("1. General", "Enabled", true, "Master switch for the mod. When disabled the game's normal first-person camera is used.");
			ThirdPersonByDefault = cfg.Bind<bool>("1. General", "ThirdPersonByDefault", true, "Start in third person at the medium distance. The toggle key cycles near, medium, far, then first person.");
			StartOnLeftShoulder = cfg.Bind<bool>("1. General", "StartOnLeftShoulder", false, "false = camera over the right shoulder, so the character appears on the left of the screen (GTA/RDR style). true = camera over the left shoulder, so the character appears on the right.");
			ToggleViewKey = cfg.Bind<KeyCode>("1. General", "ToggleViewKey", (KeyCode)118, "Key that cycles third-person near, third-person medium, third-person far, then first person.");
			SwapShoulderKey = cfg.Bind<KeyCode>("1. General", "SwapShoulderKey", (KeyCode)120, "Key that swaps the camera to the other shoulder. Tap it to swap; hold it to orbit the camera around the character.");
			OrbitHoldSeconds = cfg.Bind<float>("1. General", "OrbitHoldSeconds", 0.3f, new ConfigDescription("How long the shoulder-swap key must be held before the orbit camera activates. Shorter presses swap shoulders instead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			Distance = cfg.Bind<float>("2. Camera", "Distance", 2.4f, new ConfigDescription("Third-person medium camera distance behind the character, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 8f), Array.Empty<object>()));
			NearDistance = cfg.Bind<float>("2. Camera", "NearDistance", 1.7f, new ConfigDescription("Third-person near camera distance behind the character, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 8f), Array.Empty<object>()));
			FarDistance = cfg.Bind<float>("2. Camera", "FarDistance", 3.8f, new ConfigDescription("Third-person far camera distance behind the character, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>()));
			ShoulderOffset = cfg.Bind<float>("2. Camera", "ShoulderOffset", 0.65f, new ConfigDescription("How far the camera is offset to the side of the character, in metres. Larger values push the character farther off-centre.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			HeightOffset = cfg.Bind<float>("2. Camera", "HeightOffset", 0.25f, new ConfigDescription("Vertical offset of the camera pivot above the character's head, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.75f, 1.5f), Array.Empty<object>()));
			TransitionSeconds = cfg.Bind<float>("2. Camera", "TransitionSeconds", 0.18f, new ConfigDescription("Time it takes to blend between first person and third person, and to ease into orbit mode.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 2f), Array.Empty<object>()));
			PositionSharpness = cfg.Bind<float>("2. Camera", "PositionSharpness", 16f, new ConfigDescription("How quickly the third-person camera follows the character. Higher is snappier, lower is floatier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
			RotationSharpness = cfg.Bind<float>("2. Camera", "RotationSharpness", 28f, new ConfigDescription("How quickly the camera aligns with the aim direction. Higher is snappier, lower is smoother.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
			ShoulderSwapSharpness = cfg.Bind<float>("2. Camera", "ShoulderSwapSharpness", 14f, new ConfigDescription("How quickly the camera slides from one shoulder to the other.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
			CollisionRadius = cfg.Bind<float>("2. Camera", "CollisionRadius", 0.18f, new ConfigDescription("Radius of the sphere used to keep the camera out of walls and terrain. Set to 0 to use a plain raycast.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ThirdPersonFovBonus = cfg.Bind<float>("2. Camera", "ThirdPersonFovBonus", 0f, new ConfigDescription("Extra field of view while in third person or orbit mode. 0 keeps the game's normal FOV.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>()));
			ShowBody = cfg.Bind<bool>("3. Appearance", "ShowBody", true, "Show the local character's body and head while in third person or orbit mode.");
			ThirdPersonGrabRadius = cfg.Bind<float>("4. Interaction", "ThirdPersonGrabRadius", 0.8f, new ConfigDescription("Radius of the item/interaction sphere in third person. The game's first-person radius is 0.5. Higher values make small or slightly off-centre items easier to grab.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>()));
			ThirdPersonGrabRangeBonus = cfg.Bind<float>("4. Interaction", "ThirdPersonGrabRangeBonus", 0.5f, new ConfigDescription("Extra interaction reach in third person, in metres, after compensating for the camera being behind the character. The game's normal reach is 2 m.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
		}
	}
	[HarmonyPatch(typeof(CharacterInput), "Sample")]
	internal static class OrbitInputPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(CharacterInput __instance)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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)
			if (!ShoulderCamPlugin.OrbitActive)
			{
				return true;
			}
			__instance.lookInput = Vector2.zero;
			__instance.movementInput = Vector2.zero;
			__instance.crouchIsPressed = false;
			__instance.crouchWasPressed = false;
			__instance.crouchToggleWasPressed = false;
			__instance.sprintIsPressed = false;
			__instance.sprintToggleIsPressed = false;
			__instance.sprintWasPressed = false;
			__instance.sprintToggleWasPressed = false;
			__instance.pauseWasPressed = false;
			__instance.jumpWasPressed = false;
			__instance.jumpIsPressed = false;
			__instance.interactWasPressed = false;
			__instance.interactIsPressed = false;
			__instance.interactWasReleased = false;
			__instance.dropWasPressed = false;
			__instance.dropIsPressed = false;
			__instance.dropWasReleased = false;
			__instance.usePrimaryWasPressed = false;
			__instance.usePrimaryIsPressed = false;
			__instance.usePrimaryWasReleased = false;
			__instance.useSecondaryWasPressed = false;
			__instance.useSecondaryIsPressed = false;
			__instance.useSecondaryWasReleased = false;
			__instance.pingWasPressed = false;
			__instance.selectSlotForwardWasPressed = false;
			__instance.selectSlotBackwardWasPressed = false;
			__instance.unselectSlotWasPressed = false;
			__instance.selectBackpackWasPressed = false;
			__instance.scrollBackwardWasPressed = false;
			__instance.scrollForwardWasPressed = false;
			__instance.scrollBackwardIsPressed = false;
			__instance.scrollForwardIsPressed = false;
			__instance.scrollInput = 0f;
			__instance.emoteIsPressed = false;
			__instance.spectateLeftWasPressed = false;
			__instance.spectateRightWasPressed = false;
			__instance.pushToTalkPressed = false;
			return false;
		}
	}
	internal enum CameraMode
	{
		Near,
		Medium,
		Far,
		FirstPerson
	}
	[BepInPlugin("mj.shouldercam", "Shoulder Camera", "1.0.0")]
	public sealed class ShoulderCamPlugin : BaseUnityPlugin
	{
		public const string Guid = "mj.shouldercam";

		public const string Name = "Shoulder Camera";

		public const string Version = "1.0.0";

		internal static ShoulderCamPlugin Instance;

		internal static ManualLogSource Log;

		internal static ModConfig Cfg;

		internal static CameraMode Mode;

		internal static CameraMode LastThirdPersonMode = CameraMode.Medium;

		internal static int ShoulderSide;

		private bool _swapHeld;

		private bool _swapConsumed;

		private float _swapPressedTime;

		private Harmony _harmony;

		internal static bool ThirdPerson => Mode != CameraMode.FirstPerson;

		internal static bool OrbitActive { get; private set; }

		private void Awake()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_00ec: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Cfg = new ModConfig(((BaseUnityPlugin)this).Config);
			Mode = (Cfg.ThirdPersonByDefault.Value ? CameraMode.Medium : CameraMode.FirstPerson);
			LastThirdPersonMode = ((Mode == CameraMode.FirstPerson) ? CameraMode.Medium : Mode);
			ShoulderSide = ((!Cfg.StartOnLeftShoulder.Value) ? 1 : (-1));
			_harmony = new Harmony("mj.shouldercam");
			_harmony.PatchAll(typeof(ShoulderCamPlugin).Assembly);
			Log.LogInfo((object)("Shoulder Camera v1.0.0 loaded. View: " + ModeLabel(Mode) + ", shoulder: " + ((ShoulderSide > 0) ? "right" : "left") + ". " + $"Press {Cfg.ToggleViewKey.Value} to cycle near/medium/far/first, " + $"tap {Cfg.SwapShoulderKey.Value} to swap shoulders, " + $"hold {Cfg.SwapShoulderKey.Value} to orbit."));
		}

		private void Update()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (!Cfg.Enabled.Value)
			{
				CancelSwapGesture();
				return;
			}
			if (Input.GetKeyDown(Cfg.ToggleViewKey.Value))
			{
				Mode = NextMode(Mode);
				if (Mode != CameraMode.FirstPerson)
				{
					LastThirdPersonMode = Mode;
				}
				Log.LogInfo((object)("View switched to " + ModeLabel(Mode) + "."));
			}
			HandleSwapKey();
			if (OrbitActive)
			{
				MainCameraMovement movement = GetMovement();
				if (!_swapHeld || !CanUseOrbit(movement))
				{
					StopOrbit();
				}
			}
		}

		private void HandleSwapKey()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			KeyCode value = Cfg.SwapShoulderKey.Value;
			if (Input.GetKeyDown(value))
			{
				_swapHeld = true;
				_swapConsumed = false;
				_swapPressedTime = Time.unscaledTime;
			}
			if (!_swapHeld)
			{
				return;
			}
			if (!_swapConsumed && Time.unscaledTime - _swapPressedTime >= Cfg.OrbitHoldSeconds.Value)
			{
				_swapConsumed = true;
				if (!StartOrbit())
				{
					Log.LogWarning((object)"Orbit camera is not available right now.");
				}
			}
			if (Input.GetKeyUp(value) || !Input.GetKey(value))
			{
				_swapHeld = false;
				if (OrbitActive)
				{
					StopOrbit();
				}
				else if (!_swapConsumed)
				{
					ToggleShoulder();
				}
				_swapConsumed = false;
			}
		}

		private void ToggleShoulder()
		{
			ShoulderSide = -ShoulderSide;
			Log.LogInfo((object)("Camera shoulder swapped to the " + ((ShoulderSide > 0) ? "right" : "left") + "."));
		}

		private void CancelSwapGesture()
		{
			_swapHeld = false;
			_swapConsumed = false;
			if (OrbitActive)
			{
				StopOrbit();
			}
		}

		internal static bool StartOrbit()
		{
			MainCameraMovement movement = GetMovement();
			Character localCharacter = Character.localCharacter;
			if (!CanUseOrbit(movement) || !ShoulderCamera.BeginOrbit(localCharacter, movement, Cfg))
			{
				return false;
			}
			OrbitActive = true;
			Log.LogInfo((object)"Orbit camera enabled (holding the shoulder key).");
			return true;
		}

		internal static void StopOrbit()
		{
			if (OrbitActive)
			{
				OrbitActive = false;
				Log.LogInfo((object)"Orbit camera disabled.");
			}
		}

		private static bool CanUseOrbit(MainCameraMovement movement)
		{
			if ((Object)(object)movement == (Object)null || (Object)(object)movement.cam == (Object)null || movement.isGodCam)
			{
				return false;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null || localCharacter.refs == null || (Object)(object)localCharacter.refs.head == (Object)null || (Object)(object)localCharacter.refs.ragdoll == (Object)null)
			{
				return false;
			}
			if (localCharacter.data.dead || localCharacter.data.fullyPassedOut || localCharacter.data.usingWheel)
			{
				return false;
			}
			if ((Object)(object)movement.cam.camOverride != (Object)null || MainCameraMovement.IsSpectating)
			{
				return false;
			}
			if (LoadingScreenHandler.loading || GUIManager.InPauseMenu)
			{
				return false;
			}
			return true;
		}

		private static MainCameraMovement GetMovement()
		{
			MainCamera instance = MainCamera.instance;
			if (!((Object)(object)instance != (Object)null))
			{
				return null;
			}
			return ((Component)instance).GetComponent<MainCameraMovement>();
		}

		private static CameraMode NextMode(CameraMode mode)
		{
			return mode switch
			{
				CameraMode.Near => CameraMode.Medium, 
				CameraMode.Medium => CameraMode.Far, 
				CameraMode.Far => CameraMode.FirstPerson, 
				_ => CameraMode.Near, 
			};
		}

		internal static string ModeLabel(CameraMode mode)
		{
			return mode switch
			{
				CameraMode.Near => "third person (near)", 
				CameraMode.Medium => "third person (medium)", 
				CameraMode.Far => "third person (far)", 
				_ => "first person", 
			};
		}

		internal static float TargetDistance(ModConfig cfg)
		{
			return ((Mode == CameraMode.FirstPerson) ? LastThirdPersonMode : Mode) switch
			{
				CameraMode.Near => cfg.NearDistance.Value, 
				CameraMode.Far => cfg.FarDistance.Value, 
				_ => cfg.Distance.Value, 
			};
		}

		private void OnDestroy()
		{
			CancelSwapGesture();
			ShoulderCamera.Shutdown();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class ShoulderCamera
	{
		private const float Padding = 0.05f;

		private const float MaxOrbitPitch = 1.45f;

		private static readonly RaycastHit[] Hits = (RaycastHit[])(object)new RaycastHit[16];

		private static float _orbitYaw;

		private static float _orbitPitch;

		private static float _orbitDistance;

		private static float _orbitSensitivity = 2f;

		private static bool _orbitInvertX;

		private static bool _orbitInvertY;

		private static Vector3 _orbitStartPos;

		private static Quaternion _orbitStartRot;

		private static bool _orbitFromFirstPerson;

		private static float _orbitEntry;

		private static Vector3 _smoothPos;

		private static Quaternion _smoothRot;

		private static float _blend;

		private static float _shoulder = 1f;

		private static bool _hasState;

		private static int _localId = int.MinValue;

		private static int _movementId = int.MinValue;

		private static HideTheBody _hider;

		private static MethodInfo _toggleMethod;

		private static FieldInfo _isShowingField;

		private static Renderer[] _faceRenderers;

		private static int _hiderId = int.MinValue;

		private static bool _weDisabledBodyHider;

		private static int _collisionMask = int.MinValue;

		private static bool _loggedMaskFallback;

		private static MonoBehaviour _stableCameraBodyHider;

		private static bool _stableCameraSearchDone;

		private static int _stableCameraSearchMovementId = int.MinValue;

		internal static bool ThirdPersonActive { get; private set; }

		internal static float CameraToHeadDistance(Character local)
		{
			//IL_003f: 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)
			MainCamera instance = MainCamera.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)local == (Object)null || local.refs == null || (Object)(object)local.refs.head == (Object)null)
			{
				return 0f;
			}
			return Vector3.Distance(((Component)instance).transform.position, local.refs.head.transform.position);
		}

		internal static void Shutdown()
		{
			ResetState();
		}

		internal static bool BeginOrbit(Character local, MainCameraMovement movement, ModConfig cfg)
		{
			//IL_0052: 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_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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_00a4: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: 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_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)local == (Object)null || local.refs == null || (Object)(object)local.refs.head == (Object)null || (Object)(object)local.refs.ragdoll == (Object)null || (Object)(object)movement == (Object)null)
			{
				return false;
			}
			Vector3 val = local.refs.head.transform.position + Vector3.up * cfg.HeightOffset.Value;
			Vector3 val2 = ((Component)movement).transform.position - val;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			_orbitFromFirstPerson = magnitude < 0.5f;
			_orbitStartPos = ((Component)movement).transform.position;
			_orbitStartRot = ((Component)movement).transform.rotation;
			_orbitEntry = 0f;
			if (magnitude < 0.5f)
			{
				Vector3 forward = ((Component)movement).transform.forward;
				Vector3 forward2 = default(Vector3);
				((Vector3)(ref forward2))..ctor(forward.x, 0f, forward.z);
				if (((Vector3)(ref forward2)).sqrMagnitude < 1E-06f)
				{
					forward2 = Vector3.forward;
				}
				((Vector3)(ref forward2)).Normalize();
				Vector3 val3 = -forward2;
				_orbitYaw = Mathf.Atan2(val3.x, val3.z);
				_orbitPitch = 0f;
			}
			else
			{
				Vector3 val4 = val2 / magnitude;
				_orbitYaw = Mathf.Atan2(val4.x, val4.z);
				_orbitPitch = Mathf.Asin(Mathf.Clamp(val4.y, -1f, 1f));
			}
			_orbitYaw = Mathf.Repeat(_orbitYaw, MathF.PI * 2f);
			_orbitPitch = Mathf.Clamp(_orbitPitch, -1.45f, 1.45f);
			_orbitDistance = Mathf.Max(0.5f, ShoulderCamPlugin.TargetDistance(cfg));
			_localId = ((Object)local).GetInstanceID();
			_movementId = ((Object)movement).GetInstanceID();
			_hasState = true;
			_blend = 1f;
			_smoothPos = ((Component)movement).transform.position;
			_smoothRot = ((Component)movement).transform.rotation;
			ReadOrbitSettings();
			bool flag = cfg.ShowBody.Value && !_orbitFromFirstPerson;
			SetBodyVisible(local, flag, cfg);
			SetStableCameraBodyHider(movement, flag);
			return true;
		}

		internal static void Apply(MainCameraMovement movement)
		{
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: 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_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: 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_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: 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_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: 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)
			ModConfig cfg = ShoulderCamPlugin.Cfg;
			Character localCharacter = Character.localCharacter;
			ThirdPersonActive = false;
			if (!cfg.Enabled.Value || (Object)(object)movement == (Object)null || (Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null || localCharacter.refs == null || (Object)(object)localCharacter.refs.ragdoll == (Object)null || (Object)(object)localCharacter.refs.head == (Object)null)
			{
				ResetState();
				return;
			}
			if (movement.isGodCam || (Object)(object)movement.cam.camOverride != (Object)null || MainCameraMovement.IsSpectating || localCharacter.data.dead || localCharacter.data.fullyPassedOut)
			{
				ResetState();
				return;
			}
			if (ShoulderCamPlugin.OrbitActive)
			{
				ApplyOrbit(localCharacter, movement, cfg);
				return;
			}
			CharacterData data = localCharacter.data;
			float num = Mathf.Max(Time.deltaTime, 0.0001f);
			ResetForNewCharacter(localCharacter, movement);
			Vector3 val = data.lookDirection;
			if (((Vector3)(ref val)).sqrMagnitude < 1E-06f)
			{
				val = ((Component)movement).transform.forward;
			}
			((Vector3)(ref val)).Normalize();
			Vector3 val2 = data.lookDirection_Right;
			if (((Vector3)(ref val2)).sqrMagnitude < 1E-06f)
			{
				val2 = Vector3.Cross(Vector3.up, val);
			}
			if (((Vector3)(ref val2)).sqrMagnitude < 1E-06f)
			{
				val2 = Vector3.Cross(Vector3.forward, val);
			}
			if (((Vector3)(ref val2)).sqrMagnitude < 1E-06f)
			{
				val2 = ((Component)movement).transform.right;
			}
			((Vector3)(ref val2)).Normalize();
			Vector3 val3 = data.lookDirection_Up;
			if (((Vector3)(ref val3)).sqrMagnitude < 1E-06f || Mathf.Abs(Vector3.Dot(((Vector3)(ref val3)).normalized, val)) > 0.99f)
			{
				val3 = ((Mathf.Abs(Vector3.Dot(val, Vector3.up)) > 0.99f) ? Vector3.forward : Vector3.up);
			}
			((Vector3)(ref val3)).Normalize();
			float num2 = Mathf.Max(1f, cfg.ShoulderSwapSharpness.Value);
			float num3 = ShoulderCamPlugin.ShoulderSide;
			_shoulder = Mathf.Lerp(_shoulder, num3, 1f - Mathf.Exp((0f - num2) * num));
			float num4 = (ShoulderCamPlugin.ThirdPerson ? 1f : 0f);
			float num5 = Mathf.Max(0.01f, cfg.TransitionSeconds.Value);
			_blend = Mathf.MoveTowards(_blend, num4, num / num5);
			if (_blend <= 0.0001f)
			{
				_smoothPos = ((Component)movement).transform.position;
				_smoothRot = ((Component)movement).transform.rotation;
				SetBodyVisible(localCharacter, visible: false, cfg);
				SetStableCameraBodyHider(movement, thirdPerson: false);
				return;
			}
			Vector3 val4 = localCharacter.refs.head.transform.position + Vector3.up * cfg.HeightOffset.Value;
			float num6 = ShoulderCamPlugin.TargetDistance(cfg);
			Vector3 desired = val4 - val * num6 + val2 * (cfg.ShoulderOffset.Value * _shoulder);
			desired = ResolveCameraCollision(localCharacter, val4, desired, cfg);
			Quaternion val5 = Quaternion.LookRotation(val, val3);
			float num7 = Mathf.Max(1f, cfg.PositionSharpness.Value);
			_smoothPos = Vector3.Lerp(_smoothPos, desired, 1f - Mathf.Exp((0f - num7) * num));
			float num8 = Mathf.Max(1f, cfg.RotationSharpness.Value);
			_smoothRot = Quaternion.Slerp(_smoothRot, val5, 1f - Mathf.Exp((0f - num8) * num));
			float num9 = Mathf.SmoothStep(0f, 1f, _blend);
			Vector3 position = ((Component)movement).transform.position;
			Quaternion rotation = ((Component)movement).transform.rotation;
			((Component)movement).transform.position = Vector3.Lerp(position, _smoothPos, num9);
			((Component)movement).transform.rotation = Quaternion.Slerp(rotation, _smoothRot, num9);
			float value = cfg.ThirdPersonFovBonus.Value;
			if (value > 0.0001f)
			{
				Camera cam = movement.cam.cam;
				cam.fieldOfView += value * num9;
			}
			ThirdPersonActive = _blend > 0.02f;
			bool flag = ShoulderCamPlugin.ThirdPerson && _blend > 0.4f;
			SetBodyVisible(localCharacter, flag, cfg);
			SetStableCameraBodyHider(movement, flag);
		}

		private static void ApplyOrbit(Character local, MainCameraMovement movement, ModConfig cfg)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_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_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: 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_01bb: 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_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			_localId = ((Object)local).GetInstanceID();
			_movementId = ((Object)movement).GetInstanceID();
			_hasState = true;
			Vector2 val = ReadOrbitLook();
			float num = val.x * _orbitSensitivity * (_orbitInvertX ? (-1f) : 1f) * (MathF.PI / 180f);
			float num2 = val.y * _orbitSensitivity * (_orbitInvertY ? (-1f) : 1f) * (MathF.PI / 180f);
			_orbitYaw = Mathf.Repeat(_orbitYaw + num, MathF.PI * 2f);
			_orbitPitch = Mathf.Clamp(_orbitPitch - num2, -1.45f, 1.45f);
			Vector3 val2 = local.refs.head.transform.position + Vector3.up * cfg.HeightOffset.Value;
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(Mathf.Sin(_orbitYaw) * Mathf.Cos(_orbitPitch), Mathf.Sin(_orbitPitch), Mathf.Cos(_orbitYaw) * Mathf.Cos(_orbitPitch));
			Vector3 desired = val2 + val3 * _orbitDistance;
			desired = ResolveCameraCollision(local, val2, desired, cfg);
			Vector3 val4 = val2 - desired;
			if (((Vector3)(ref val4)).sqrMagnitude < 1E-06f)
			{
				val4 = -val3;
			}
			Quaternion val5 = Quaternion.LookRotation(val4, Vector3.up);
			float num3 = Mathf.Max(0.01f, cfg.TransitionSeconds.Value);
			_orbitEntry = Mathf.MoveTowards(_orbitEntry, 1f, Time.deltaTime / num3);
			float num4 = Mathf.SmoothStep(0f, 1f, _orbitEntry);
			if (num4 < 1f)
			{
				desired = Vector3.Lerp(_orbitStartPos, desired, num4);
				val5 = Quaternion.Slerp(_orbitStartRot, val5, num4);
			}
			((Component)movement).transform.position = desired;
			((Component)movement).transform.rotation = val5;
			_smoothPos = desired;
			_smoothRot = val5;
			_blend = 1f;
			float value = cfg.ThirdPersonFovBonus.Value;
			if (value > 0.0001f)
			{
				float num5 = (_orbitFromFirstPerson ? num4 : 1f);
				Camera cam = movement.cam.cam;
				cam.fieldOfView += value * num5;
			}
			bool flag = cfg.ShowBody.Value && (!_orbitFromFirstPerson || _orbitEntry > 0.4f);
			SetBodyVisible(local, flag, cfg);
			SetStableCameraBodyHider(movement, flag);
		}

		private static Vector2 ReadOrbitLook()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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)
			InputAction action_look = CharacterInput.action_look;
			if (action_look != null)
			{
				try
				{
					return action_look.ReadValue<Vector2>();
				}
				catch
				{
				}
			}
			return new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
		}

		private static void ReadOrbitSettings()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Invalid comparison between Unknown and I4
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Invalid comparison between Unknown and I4
			_orbitSensitivity = 2f;
			_orbitInvertX = false;
			_orbitInvertY = false;
			try
			{
				GameHandler instance = GameHandler.Instance;
				SettingsHandler val = (((Object)(object)instance != (Object)null) ? instance.SettingsHandler : null);
				if (val != null)
				{
					MouseSensitivitySetting setting = val.GetSetting<MouseSensitivitySetting>();
					if (setting != null)
					{
						_orbitSensitivity = Mathf.Max(0.01f, ((FloatSetting)setting).Value);
					}
					InvertXSetting setting2 = val.GetSetting<InvertXSetting>();
					if (setting2 != null)
					{
						_orbitInvertX = (int)((EnumSetting<OffOnMode>)(object)setting2).Value == 1;
					}
					InvertYSetting setting3 = val.GetSetting<InvertYSetting>();
					if (setting3 != null)
					{
						_orbitInvertY = (int)((EnumSetting<OffOnMode>)(object)setting3).Value == 1;
					}
				}
			}
			catch
			{
			}
		}

		private static void ResetForNewCharacter(Character local, MainCameraMovement movement)
		{
			//IL_0056: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)local).GetInstanceID();
			int instanceID2 = ((Object)movement).GetInstanceID();
			if (!_hasState || instanceID != _localId || instanceID2 != _movementId)
			{
				_localId = instanceID;
				_movementId = instanceID2;
				_hasState = true;
				_blend = (ShoulderCamPlugin.ThirdPerson ? 1f : 0f);
				_smoothPos = ((Component)movement).transform.position;
				_smoothRot = ((Component)movement).transform.rotation;
				_shoulder = ShoulderCamPlugin.ShoulderSide;
				RestoreBodyHider();
				_hider = null;
				_hiderId = int.MinValue;
				_faceRenderers = null;
			}
		}

		private static void ResetState()
		{
			_hasState = false;
			_localId = int.MinValue;
			_movementId = int.MinValue;
			_blend = 0f;
			ThirdPersonActive = false;
			RestoreStableCameraBodyHider();
			RestoreBodyHider();
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null && !localCharacter.data.dead && !localCharacter.data.fullyPassedOut)
			{
				SetBodyVisible(localCharacter, visible: false, ShoulderCamPlugin.Cfg);
			}
		}

		private static void SetStableCameraBodyHider(MainCameraMovement movement, bool thirdPerson)
		{
			if (thirdPerson)
			{
				if ((Object)(object)_stableCameraBodyHider == (Object)null)
				{
					int instanceID = ((Object)movement).GetInstanceID();
					if (!_stableCameraSearchDone || _stableCameraSearchMovementId != instanceID)
					{
						_stableCameraSearchDone = true;
						_stableCameraSearchMovementId = instanceID;
						MonoBehaviour[] components = ((Component)movement).GetComponents<MonoBehaviour>();
						foreach (MonoBehaviour val in components)
						{
							if ((Object)(object)val != (Object)null && ((object)val).GetType().FullName == "Linkoid.Peak.StableCamera.MainCameraBodyHider")
							{
								_stableCameraBodyHider = val;
								ShoulderCamPlugin.Log.LogInfo((object)"StableCamera detected: its body hider will be paused while the third-person body is visible.");
								break;
							}
						}
					}
				}
				if ((Object)(object)_stableCameraBodyHider != (Object)null)
				{
					((Behaviour)_stableCameraBodyHider).enabled = false;
				}
			}
			else
			{
				RestoreStableCameraBodyHider();
			}
		}

		private static void RestoreStableCameraBodyHider()
		{
			if ((Object)(object)_stableCameraBodyHider != (Object)null && !((Behaviour)_stableCameraBodyHider).enabled)
			{
				((Behaviour)_stableCameraBodyHider).enabled = true;
			}
		}

		private static Vector3 ResolveCameraCollision(Character local, Vector3 pivot, Vector3 desired, ModConfig cfg)
		{
			//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_001a: 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_0021: 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_0093: 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_0041: 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_00b0: 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_00b7: 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_0067: 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_00fe: 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)
			//IL_0106: 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)
			Vector3 val = desired - pivot;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.0001f)
			{
				return desired;
			}
			Vector3 val2 = val / magnitude;
			int collisionMask = GetCollisionMask();
			float value = cfg.CollisionRadius.Value;
			float num = magnitude;
			if (value > 0.001f)
			{
				int num2 = Physics.SphereCastNonAlloc(pivot, value, val2, Hits, magnitude, collisionMask, (QueryTriggerInteraction)1);
				for (int i = 0; i < num2; i++)
				{
					RaycastHit hit = Hits[i];
					if (IsUsableHit(hit, local) && ((RaycastHit)(ref hit)).distance < num)
					{
						num = ((RaycastHit)(ref hit)).distance;
					}
				}
			}
			else
			{
				int num3 = Physics.RaycastNonAlloc(pivot, val2, Hits, magnitude, collisionMask, (QueryTriggerInteraction)1);
				for (int j = 0; j < num3; j++)
				{
					RaycastHit hit2 = Hits[j];
					if (IsUsableHit(hit2, local) && ((RaycastHit)(ref hit2)).distance < num)
					{
						num = ((RaycastHit)(ref hit2)).distance;
					}
				}
			}
			if (num >= magnitude)
			{
				return desired;
			}
			float num4 = Mathf.Clamp(num - 0.05f, 0.05f, magnitude);
			return pivot + val2 * num4;
		}

		private static bool IsUsableHit(RaycastHit hit, Character local)
		{
			if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null)
			{
				return false;
			}
			if ((Object)(object)local != (Object)null && ((Component)((RaycastHit)(ref hit)).collider).transform.IsChildOf(((Component)local).transform))
			{
				return false;
			}
			return true;
		}

		private static int GetCollisionMask()
		{
			if (_collisionMask != int.MinValue)
			{
				return _collisionMask;
			}
			_collisionMask = LayerMask.GetMask(new string[2] { "Terrain", "Map" });
			if (_collisionMask == 0)
			{
				_collisionMask = -1;
				if (!_loggedMaskFallback)
				{
					_loggedMaskFallback = true;
					ShoulderCamPlugin.Log.LogWarning((object)"Could not find the Terrain/Map layers; camera collision will test all layers.");
				}
			}
			return _collisionMask;
		}

		private static void SetBodyVisible(Character local, bool visible, ModConfig cfg)
		{
			if ((Object)(object)local == (Object)null || local.refs == null || (Object)(object)local.refs.hideTheBody == (Object)null)
			{
				return;
			}
			HideTheBody hideTheBody = local.refs.hideTheBody;
			if ((Object)(object)hideTheBody != (Object)(object)_hider || ((Object)hideTheBody).GetInstanceID() != _hiderId)
			{
				RestoreBodyHider();
				_hider = hideTheBody;
				_hiderId = ((Object)hideTheBody).GetInstanceID();
				_toggleMethod = AccessTools.Method(typeof(HideTheBody), "Toggle", new Type[1] { typeof(bool) }, (Type[])null);
				_isShowingField = AccessTools.Field(typeof(HideTheBody), "isShowing");
				_faceRenderers = (((Object)(object)hideTheBody.face != (Object)null) ? ((Component)hideTheBody.face).GetComponentsInChildren<Renderer>(true) : null);
			}
			if (visible && cfg.ShowBody.Value)
			{
				if (((Behaviour)hideTheBody).enabled)
				{
					((Behaviour)hideTheBody).enabled = false;
					_weDisabledBodyHider = true;
				}
				if (!IsBodyVisible(hideTheBody))
				{
					SetShowing(hideTheBody, show: true);
				}
				EnableBodyRenderers(hideTheBody, enabled: true);
			}
			else
			{
				RestoreBodyHider();
				if (IsBodyVisible(hideTheBody))
				{
					SetShowing(hideTheBody, show: false);
				}
			}
		}

		private static bool IsBodyVisible(HideTheBody hider)
		{
			if (_isShowingField == null)
			{
				return false;
			}
			return (bool)_isShowingField.GetValue(hider);
		}

		private static void SetShowing(HideTheBody hider, bool show)
		{
			if (_toggleMethod == null)
			{
				return;
			}
			try
			{
				_toggleMethod.Invoke(hider, new object[1] { show });
			}
			catch (Exception ex)
			{
				ShoulderCamPlugin.Log.LogWarning((object)("Could not change body visibility: " + ex.Message));
				_toggleMethod = null;
			}
		}

		private static void RestoreBodyHider()
		{
			if (_weDisabledBodyHider && (Object)(object)_hider != (Object)null)
			{
				((Behaviour)_hider).enabled = true;
			}
			_weDisabledBodyHider = false;
		}

		private static void EnableBodyRenderers(HideTheBody hider, bool enabled)
		{
			Enable((Renderer)(object)hider.body, enabled);
			Enable(hider.headRend, enabled);
			Enable((Renderer)(object)hider.sash, enabled);
			Enable(hider.medal, enabled);
			if (hider.costumes != null)
			{
				for (int i = 0; i < hider.costumes.Length; i++)
				{
					Enable((Renderer)(object)hider.costumes[i], enabled);
				}
			}
			if ((Object)(object)hider.refs != (Object)null && hider.refs.playerHats != null)
			{
				for (int j = 0; j < hider.refs.playerHats.Length; j++)
				{
					Enable(hider.refs.playerHats[j], enabled);
				}
			}
			if (_faceRenderers != null)
			{
				for (int k = 0; k < _faceRenderers.Length; k++)
				{
					Enable(_faceRenderers[k], enabled);
				}
			}
		}

		private static void Enable(Renderer renderer, bool enabled)
		{
			if ((Object)(object)renderer != (Object)null)
			{
				renderer.enabled = enabled;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}