Decompiled source of Repo Native ThirdPerson ActionMovement v1.2.0

BepInEx\plugins\Repo_Native_ThirdPerson_ActionMovement\RepoThirdPerson.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering.PostProcessing;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RepoThirdPerson")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RepoThirdPerson")]
[assembly: AssemblyTitle("RepoThirdPerson")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace RepoThirdPerson
{
	[BepInPlugin("com.reponativemods.thirdperson", "REPO Native Third Person", "1.2.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private struct ClipPlaneState
		{
			public float Near;

			public float Far;
		}

		private static class RepoUpdatePatches
		{
			[CompilerGenerated]
			private sealed class <PlayerControllerFixedUpdateTranspiler>d__2 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable
			{
				private int <>1__state;

				private CodeInstruction <>2__current;

				private int <>l__initialThreadId;

				private IEnumerable<CodeInstruction> instructions;

				public IEnumerable<CodeInstruction> <>3__instructions;

				private List<CodeInstruction> <list>5__2;

				private FieldInfo <vector3Y>5__3;

				private MethodInfo <euler>5__4;

				private MethodInfo <resolveYaw>5__5;

				private bool <patched>5__6;

				private int <i>5__7;

				CodeInstruction IEnumerator<CodeInstruction>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <PlayerControllerFixedUpdateTranspiler>d__2(int <>1__state)
				{
					this.<>1__state = <>1__state;
					<>l__initialThreadId = Environment.CurrentManagedThreadId;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<list>5__2 = null;
					<vector3Y>5__3 = null;
					<euler>5__4 = null;
					<resolveYaw>5__5 = null;
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_016e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0178: Expected O, but got Unknown
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<list>5__2 = new List<CodeInstruction>(instructions);
						<vector3Y>5__3 = AccessTools.Field(typeof(Vector3), "y");
						<euler>5__4 = AccessTools.Method(typeof(Quaternion), "Euler", new Type[3]
						{
							typeof(float),
							typeof(float),
							typeof(float)
						}, (Type[])null);
						<resolveYaw>5__5 = AccessTools.Method(typeof(RepoUpdatePatches), "ResolveActionMovementYaw", (Type[])null, (Type[])null);
						<patched>5__6 = false;
						<i>5__7 = 0;
						break;
					case 1:
						<>1__state = -1;
						if (!<patched>5__6 && <list>5__2[<i>5__7].opcode == OpCodes.Ldfld && object.Equals(<list>5__2[<i>5__7].operand, <vector3Y>5__3))
						{
							for (int i = <i>5__7 + 1; i < <list>5__2.Count && i <= <i>5__7 + 4; i++)
							{
								if (Calls(<list>5__2[i], <euler>5__4))
								{
									<>2__current = new CodeInstruction(OpCodes.Call, (object)<resolveYaw>5__5);
									<>1__state = 2;
									return true;
								}
							}
						}
						goto IL_01ae;
					case 2:
						{
							<>1__state = -1;
							<patched>5__6 = true;
							goto IL_01ae;
						}
						IL_01ae:
						<i>5__7++;
						break;
					}
					if (<i>5__7 < <list>5__2.Count)
					{
						<>2__current = <list>5__2[<i>5__7];
						<>1__state = 1;
						return true;
					}
					return false;
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}

				[DebuggerHidden]
				IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
				{
					<PlayerControllerFixedUpdateTranspiler>d__2 <PlayerControllerFixedUpdateTranspiler>d__;
					if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
					{
						<>1__state = 0;
						<PlayerControllerFixedUpdateTranspiler>d__ = this;
					}
					else
					{
						<PlayerControllerFixedUpdateTranspiler>d__ = new <PlayerControllerFixedUpdateTranspiler>d__2(0);
					}
					<PlayerControllerFixedUpdateTranspiler>d__.instructions = <>3__instructions;
					return <PlayerControllerFixedUpdateTranspiler>d__;
				}

				[DebuggerHidden]
				IEnumerator IEnumerable.GetEnumerator()
				{
					return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
				}
			}

			[HarmonyPostfix]
			[HarmonyPatch(typeof(PlayerController), "Update")]
			private static void PlayerControllerUpdatePostfix()
			{
				Instance?.TickInput();
			}

			[HarmonyPrefix]
			[HarmonyPriority(800)]
			[HarmonyPatch(typeof(PlayerController), "FixedUpdate")]
			private static void PlayerControllerFixedUpdatePrefix(PlayerController __instance)
			{
				Instance?.BeginActionMovementRewrite(__instance);
			}

			[IteratorStateMachine(typeof(<PlayerControllerFixedUpdateTranspiler>d__2))]
			[HarmonyTranspiler]
			[HarmonyPatch(typeof(PlayerController), "FixedUpdate")]
			private static IEnumerable<CodeInstruction> PlayerControllerFixedUpdateTranspiler(IEnumerable<CodeInstruction> instructions)
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <PlayerControllerFixedUpdateTranspiler>d__2(-2)
				{
					<>3__instructions = instructions
				};
			}

			private static bool Calls(CodeInstruction instruction, MethodInfo method)
			{
				if (instruction.opcode == OpCodes.Call)
				{
					return object.Equals(instruction.operand, method);
				}
				return false;
			}

			private static float ResolveActionMovementYaw(float originalYaw)
			{
				if ((Object)(object)Instance == (Object)null)
				{
					return originalYaw;
				}
				if (IsActionMovementCameraLockHeld() && Instance.TryGetGameplayAimYaw(out var yaw))
				{
					_hasRewriteTurnYaw = true;
					_lastRewriteTurnYaw = yaw;
					return yaw;
				}
				if (!Instance.CanAcceptActionMovementInput())
				{
					return originalYaw;
				}
				if (_rewriteMovementInput)
				{
					return _rewriteTurnYaw;
				}
				if (!_hasRewriteTurnYaw)
				{
					return originalYaw;
				}
				return _lastRewriteTurnYaw;
			}

			internal static bool IsActionMovementCameraLockHeld()
			{
				if (Mouse.current == null || Mouse.current.rightButton == null || !Mouse.current.rightButton.isPressed)
				{
					return Input.GetMouseButton(1);
				}
				return true;
			}

			[HarmonyPostfix]
			[HarmonyPriority(0)]
			[HarmonyPatch(typeof(PlayerController), "FixedUpdate")]
			private static void PlayerControllerFixedUpdatePostfix(PlayerController __instance)
			{
				Instance?.TickActionMovementAfterFixedUpdate(__instance);
			}

			[HarmonyFinalizer]
			[HarmonyPriority(0)]
			[HarmonyPatch(typeof(PlayerController), "FixedUpdate")]
			private static void PlayerControllerFixedUpdateFinalizer()
			{
				Instance?.EndActionMovementRewrite();
			}

			[HarmonyPostfix]
			[HarmonyPatch(typeof(SemiFunc), "InputMovementX")]
			private static void SemiFuncInputMovementXPostfix(ref float __result)
			{
				if (_rewriteMovementInput)
				{
					__result = _rewriteMovementX;
				}
			}

			[HarmonyPostfix]
			[HarmonyPatch(typeof(SemiFunc), "InputMovementY")]
			private static void SemiFuncInputMovementYPostfix(ref float __result)
			{
				if (_rewriteMovementInput)
				{
					__result = _rewriteMovementY;
				}
			}

			[HarmonyPostfix]
			[HarmonyPriority(0)]
			[HarmonyPatch(typeof(PlayerAvatarVisuals), "Update")]
			private static void PlayerAvatarVisualsUpdatePostfix(PlayerAvatarVisuals __instance)
			{
				Instance?.TickActionMovementVisuals(__instance);
			}

			[HarmonyPriority(0)]
			private static void ModdedModelPlayerAvatarUpdatePostfix(object __instance)
			{
				Instance?.TickModdedModelPlayerAvatarPostUpdate(__instance);
			}

			[HarmonyPostfix]
			[HarmonyPatch(typeof(CameraPosition), "Update")]
			private static void CameraPositionUpdatePostfix()
			{
			}

			[HarmonyPostfix]
			[HarmonyPatch(typeof(PlayerLocalCamera), "GetOverrideTransform")]
			private static void PlayerLocalCameraGetOverrideTransformPostfix(PlayerLocalCamera __instance, ref Transform __result)
			{
				Instance?.TryGetSelectionOverride(__instance, ref __result);
			}
		}

		public const string PluginGuid = "com.reponativemods.thirdperson";

		public const string PluginName = "REPO Native Third Person";

		public const string PluginVersion = "1.2.0";

		private const string SelectionTransformName = "REPO Native Third Person Selection Transform";

		private const string ToggleActionName = "REPO Native Third Person Toggle";

		private const string ZoomInActionName = "REPO Native Third Person Zoom In";

		private const string ZoomOutActionName = "REPO Native Third Person Zoom Out";

		private const string DefaultLayerName = "Default";

		private const string GroundLayerName = "Ground";

		private const string WallLayerName = "Wall";

		private const string PlayerLayerName = "Player";

		private const float InputDeadZone = 0.001f;

		private const float MinimumCameraCastDistance = 0.001f;

		private const float MinimumSelectionDirectionSqrMagnitude = 0.0001f;

		private const float MinimumConfiguredDistance = 0.1f;

		private const float CameraPositionOverrideDuration = 0.1f;

		private const float ShowSelfOverrideDuration = 0.15f;

		private ConfigEntry<KeyCode> _toggleKey;

		private ConfigEntry<KeyCode> _zoomInKey;

		private ConfigEntry<KeyCode> _zoomOutKey;

		private ConfigEntry<KeyCode> _resetOffsetsKey;

		private ConfigEntry<float> _scrollSensitivity;

		private ConfigEntry<float> _keyZoomSpeed;

		private ConfigEntry<float> _offsetAdjustSpeed;

		private ConfigEntry<float> _offsetX;

		private ConfigEntry<float> _offsetY;

		private ConfigEntry<float> _defaultDistance;

		private ConfigEntry<float> _minDistance;

		private ConfigEntry<float> _maxDistance;

		private ConfigEntry<float> _collisionRadius;

		private ConfigEntry<float> _collisionPadding;

		private ConfigEntry<float> _minimumFarClipPlane;

		private ConfigEntry<float> _nearClipPlane;

		private ConfigEntry<bool> _cameraCenteredSelection;

		private ConfigEntry<float> _selectionMaxDistance;

		private ConfigEntry<bool> _actionMovementEnabled;

		private ConfigEntry<float> _actionTurnSpeed;

		private ConfigEntry<bool> _actionMovementWhileGrabbing;

		private ConfigEntry<bool> _forceLocalModdedModel;

		private readonly Dictionary<Camera, ClipPlaneState> _originalClipPlanes = new Dictionary<Camera, ClipPlaneState>();

		private readonly Dictionary<Renderer, MotionVectorGenerationMode> _originalRendererMotionVectors = new Dictionary<Renderer, MotionVectorGenerationMode>();

		private readonly Dictionary<GameObject, int> _originalRendererLayers = new Dictionary<GameObject, int>();

		private readonly List<Camera> _cameraBuffer = new List<Camera>(16);

		private bool _thirdPersonActive;

		private float _currentDistance;

		private int _collisionMask;

		private InputAction _toggleAction;

		private InputAction _zoomInAction;

		private InputAction _zoomOutAction;

		private Harmony _harmony;

		private Transform _selectionTransform;

		private int _lastInputTickFrame = -1;

		private int _lastCameraTickFrame = -1;

		private bool _temporarilyFirstPerson;

		private float _startingOffsetX;

		private float _startingOffsetY;

		private float _runtimeOffsetX;

		private float _runtimeOffsetY;

		private int _lastActionMovementTickFrame = -1;

		private Vector3 _lastActionMoveDirection = Vector3.zero;

		private float _lastActionMoveDirectionTime;

		private bool _loggedModelCompatibility;

		private bool _loggedModelCompatibilityMissing;

		private Type _moddedModelPlayerAvatarType;

		private FieldInfo _forceShowLocalModelField;

		private FieldInfo _currentModelInstanceField;

		private FieldInfo _cachedModelRenderersField;

		private MethodInfo _applyModelToVisualMethod;

		private bool _moddedModelUpdatePatched;

		private PlayerAvatar _cachedModelAvatar;

		private Component _cachedModelComponent;

		private GameObject _cachedModelInstance;

		private Renderer[] _cachedForcedRenderers;

		private bool _localModdedModelVisible;

		private PlayerAvatarVisuals _cachedAvatarVisualsForMotionVectors;

		private Renderer[] _cachedAvatarVisualRenderers;

		private float _nextModelCompatibilityRetryTime;

		private float _nextRendererRefreshTime;

		private float _nextAvatarRendererRefreshTime;

		private bool _motionBlurOverrideActive;

		private bool _motionBlurOriginalActive;

		private float _motionBlurOriginalShutterAngle;

		private static FieldInfo _menuCurrentPageField;

		private static bool _rewriteMovementInput;

		private static float _rewriteMovementX;

		private static float _rewriteMovementY;

		private static float _rewriteTurnYaw;

		private static float _lastRewriteTurnYaw;

		private static bool _hasRewriteTurnYaw;

		private static Quaternion _visualFacingRotation = Quaternion.identity;

		private static bool _hasVisualFacingRotation;

		private PlayerAvatar _lastPlayerAvatar;

		private int _lastGameState = -1;

		private FieldInfo _avatarIsDisabledField;

		private FieldInfo _avatarDeadSetField;

		private FieldInfo _postProcessingMotionBlurField;

		private FieldInfo _avatarVisualPositionField;

		private FieldInfo _avatarVisualFollowLerpField;

		private FieldInfo _avatarVisualBodySpringTargetField;

		internal static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Expected O, but got Unknown
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Expected O, but got Unknown
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Expected O, but got Unknown
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Expected O, but got Unknown
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Expected O, but got Unknown
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Expected O, but got Unknown
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Expected O, but got Unknown
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Expected O, but got Unknown
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Expected O, but got Unknown
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Expected O, but got Unknown
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Expected O, but got Unknown
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Expected O, but got Unknown
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Expected O, but got Unknown
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Expected O, but got Unknown
			//IL_052a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0534: Expected O, but got Unknown
			//IL_055a: Unknown result type (might be due to invalid IL or missing references)
			//IL_056a: Unknown result type (might be due to invalid IL or missing references)
			//IL_057a: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			KeepAliveOutsideScene(((Component)this).gameObject);
			_toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ToggleKey", (KeyCode)120, "Key to toggle third-person mode.");
			_offsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "OffsetX", 0.5f, "Horizontal shoulder offset.");
			_offsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "OffsetY", 1.6f, "Vertical offset from the local player origin.");
			_defaultDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DefaultDistance", 3f, new ConfigDescription("Default distance behind the player.", (AcceptableValueBase)new AcceptableValueRange<float>(0.25f, 25f), Array.Empty<object>()));
			_minDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "MinDistance", 1f, new ConfigDescription("Minimum zoom distance.", (AcceptableValueBase)new AcceptableValueRange<float>(0.1f, 25f), Array.Empty<object>()));
			_maxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "MaxDistance", 10f, new ConfigDescription("Maximum zoom distance.", (AcceptableValueBase)new AcceptableValueRange<float>(0.25f, 50f), Array.Empty<object>()));
			_collisionRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CollisionRadius", 0.25f, new ConfigDescription("Spherecast radius used to keep the camera out of walls.", (AcceptableValueBase)new AcceptableValueRange<float>(0.01f, 2f), Array.Empty<object>()));
			_collisionPadding = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CollisionPadding", 0.15f, new ConfigDescription("Distance kept between the camera and collision surfaces.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			_nearClipPlane = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "NearClipPlane", 0.03f, new ConfigDescription("Near clip plane while third-person is active. Lower values reduce close zoom clipping.", (AcceptableValueBase)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
			_minimumFarClipPlane = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "MinimumFarClipPlane", 1000f, new ConfigDescription("Minimum far clip plane while third-person is active. The mod also preserves any larger original far clip value.", (AcceptableValueBase)new AcceptableValueRange<float>(100f, 100000f), Array.Empty<object>()));
			_cameraCenteredSelection = ((BaseUnityPlugin)this).Config.Bind<bool>("Interaction", "CameraCenteredSelection", true, "Aim selection/grabbing at the object centered by the third-person camera while keeping the origin at the player vision transform.");
			_selectionMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Interaction", "SelectionMaxDistance", 100f, new ConfigDescription("Maximum distance used when converting the third-person camera center ray into a player-origin selection ray.", (AcceptableValueBase)new AcceptableValueRange<float>(10f, 500f), Array.Empty<object>()));
			_zoomInKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ZoomInKey", (KeyCode)270, "Key to zoom in.");
			_zoomOutKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ZoomOutKey", (KeyCode)269, "Key to zoom out.");
			_resetOffsetsKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ResetOffsetsKey", (KeyCode)278, "Key to reset runtime camera offsets to the loaded config values.");
			_scrollSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "ScrollSensitivity", 1f, new ConfigDescription("Mouse wheel zoom sensitivity.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			_keyZoomSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "KeyZoomSpeed", 5f, new ConfigDescription("Zoom speed when using zoom keys.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			_offsetAdjustSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "OffsetAdjustSpeed", 1f, new ConfigDescription("Offset adjustment speed when holding arrow keys, in world units per second.", (AcceptableValueBase)new AcceptableValueRange<float>(0.05f, 10f), Array.Empty<object>()));
			_actionMovementEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Action Movement", "Enabled", true, "When third-person is active, turn the avatar toward the camera-relative WASD direction.");
			_actionTurnSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Action Movement", "TurnSpeed", 14f, new ConfigDescription("How quickly the avatar turns toward the camera-relative movement direction.", (AcceptableValueBase)new AcceptableValueRange<float>(1f, 40f), Array.Empty<object>()));
			_actionMovementWhileGrabbing = ((BaseUnityPlugin)this).Config.Bind<bool>("Action Movement", "WhileGrabbing", false, "Keep action movement active while grabbing. Disabled by default so grab aim keeps vanilla behavior.");
			_forceLocalModdedModel = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "ForceLocalModdedModel", true, "While third-person is active, ask known model-swap mods to show the local custom model.");
			_currentDistance = ClampDistance(_defaultDistance.Value);
			_startingOffsetX = _offsetX.Value;
			_startingOffsetY = _offsetY.Value;
			_runtimeOffsetX = _startingOffsetX;
			_runtimeOffsetY = _startingOffsetY;
			_collisionMask = LayerMask.GetMask(new string[3] { "Default", "Ground", "Wall" });
			_selectionTransform = CreatePersistentTransform("REPO Native Third Person Selection Transform");
			CreateInputActions();
			_harmony = new Harmony("com.reponativemods.thirdperson");
			_harmony.PatchAll(typeof(RepoUpdatePatches));
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded action-movement build 24 with smooth visual facing, late camera updates, and 360-degree right-click flashlight lock. ToggleKey={_toggleKey.Value}, ZoomInKey={_zoomInKey.Value}, ZoomOutKey={_zoomOutKey.Value}");
		}

		private static Transform CreatePersistentTransform(string objectName)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			GameObject val = new GameObject(objectName);
			KeepAliveOutsideScene(val);
			return val.transform;
		}

		private static void KeepAliveOutsideScene(GameObject owner)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if ((Object)(object)owner != (Object)null)
			{
				owner.transform.SetParent((Transform)null, true);
				((Object)owner).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)owner);
			}
		}

		private void Update()
		{
			TickInput();
		}

		internal void TickInput()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (_lastInputTickFrame != Time.frameCount)
			{
				_lastInputTickFrame = Time.frameCount;
				if ((IsActionPressedThisFrame(_toggleAction) || IsKeyPressedThisFrame(_toggleKey.Value)) && CanToggleThirdPerson())
				{
					SetThirdPersonActive(!_thirdPersonActive);
				}
				if (_thirdPersonActive)
				{
					HandleZoomInput();
					HandleOffsetInput();
				}
			}
		}

		internal void TickActionMovement()
		{
			//IL_0048: 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_005e: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			if (_lastActionMovementTickFrame == Time.frameCount)
			{
				return;
			}
			_lastActionMovementTickFrame = Time.frameCount;
			if (!CanAcceptActionMovementInput())
			{
				return;
			}
			PlayerAvatar instance = PlayerAvatar.instance;
			CameraAim instance2 = CameraAim.Instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance2 != (Object)null)
			{
				Vector3 val = ReadCameraRelativeMoveDirection(((Component)instance2).transform);
				if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f))
				{
					_lastActionMoveDirection = val;
					_lastActionMoveDirectionTime = Time.time;
					RotateAvatarTowardMovement(instance, val);
				}
			}
		}

		internal void TickActionMovementVisuals(PlayerAvatarVisuals visuals)
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_011b: 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_009c: 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)
			if ((Object)(object)visuals == (Object)null || (Object)(object)visuals.playerAvatar == (Object)null || (Object)(object)visuals.playerAvatar != (Object)(object)PlayerAvatar.instance)
			{
				return;
			}
			if (RepoUpdatePatches.IsActionMovementCameraLockHeld() && TryGetGameplayAimRotation(out var rotation))
			{
				Quaternion val = (_hasVisualFacingRotation ? _visualFacingRotation : ((Component)visuals).transform.rotation);
				float num = Mathf.Max(1f, _actionTurnSpeed?.Value ?? 14f);
				float num2 = 1f - Mathf.Exp(0f - num * Mathf.Max(0f, Time.deltaTime));
				_visualFacingRotation = Quaternion.Slerp(val, rotation, num2);
				_hasVisualFacingRotation = true;
				ApplyVisualFacingRotation(visuals);
			}
			else
			{
				if (!CanAcceptActionMovementInput())
				{
					return;
				}
				CameraAim instance = CameraAim.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return;
				}
				Vector3 moveDirection = ReadGameInputCameraRelativeMoveDirection(((Component)instance).transform);
				if (((Vector3)(ref moveDirection)).sqrMagnitude < 0.0001f)
				{
					if (Time.time - _lastActionMoveDirectionTime > 0.2f)
					{
						return;
					}
					moveDirection = _lastActionMoveDirection;
				}
				if (!(((Vector3)(ref moveDirection)).sqrMagnitude < 0.0001f))
				{
					RotateTransformToward(((Component)visuals).transform, moveDirection);
				}
			}
		}

		internal void BeginActionMovementRewrite(PlayerController controller)
		{
			//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_0082: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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)
			//IL_00ad: 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)
			_rewriteMovementInput = false;
			if ((Object)(object)controller == (Object)null || (Object)(object)controller != (Object)(object)PlayerController.instance || !CanAcceptActionMovementInput())
			{
				return;
			}
			CameraAim instance = CameraAim.Instance;
			if ((Object)(object)instance == (Object)null || RepoUpdatePatches.IsActionMovementCameraLockHeld())
			{
				return;
			}
			float num = SemiFunc.InputMovementX();
			float num2 = SemiFunc.InputMovementY();
			if (!(Mathf.Abs(num) <= 0.001f) || !(Mathf.Abs(num2) <= 0.001f))
			{
				Vector3 val = ReadCameraRelativeMoveDirection(((Component)instance).transform, num, num2);
				if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f))
				{
					_lastActionMoveDirection = val;
					_lastActionMoveDirectionTime = Time.time;
					Quaternion val2 = ExactLookRotation(val, ((Component)controller).transform.rotation);
					Vector2 val3 = new Vector2(num, num2);
					float num3 = Mathf.Clamp01(((Vector2)(ref val3)).magnitude);
					_rewriteMovementX = 0f;
					_rewriteMovementY = Mathf.Max(0.01f, num3);
					_rewriteTurnYaw = ((Quaternion)(ref val2)).eulerAngles.y;
					_lastRewriteTurnYaw = _rewriteTurnYaw;
					_hasRewriteTurnYaw = true;
					_rewriteMovementInput = true;
				}
			}
		}

		internal void EndActionMovementRewrite()
		{
			_rewriteMovementInput = false;
		}

		internal void TickActionMovementAfterFixedUpdate(PlayerController controller)
		{
			//IL_0035: 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_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_0080: Unknown result type (might be due to invalid IL or missing references)
			if (!_rewriteMovementInput || (Object)(object)controller == (Object)null || (Object)(object)controller != (Object)(object)PlayerController.instance || !CanAcceptActionMovementInput() || (Object)(object)CameraAim.Instance == (Object)null)
			{
				return;
			}
			Vector3 lastActionMoveDirection = _lastActionMoveDirection;
			if (!(((Vector3)(ref lastActionMoveDirection)).sqrMagnitude < 0.0001f))
			{
				_lastActionMoveDirection = lastActionMoveDirection;
				_lastActionMoveDirectionTime = Time.time;
				PlayerAvatar instance = PlayerAvatar.instance;
				if ((Object)(object)instance != (Object)null && (Object)(object)instance.playerAvatarVisuals != (Object)null)
				{
					RotateVisualsTowardMovement(instance.playerAvatarVisuals, lastActionMoveDirection, Time.fixedDeltaTime);
				}
			}
		}

		internal void TickModdedModelPlayerAvatarPostUpdate(object moddedModelPlayerAvatar)
		{
			if (_thirdPersonActive && !_temporarilyFirstPerson && moddedModelPlayerAvatar != null)
			{
				object? obj = _currentModelInstanceField?.GetValue(moddedModelPlayerAvatar);
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				if (!((Object)(object)val == (Object)null))
				{
					StabilizeLocalModdedModel(val);
				}
			}
		}

		private bool CanAcceptActionMovementInput()
		{
			if (!_thirdPersonActive || _temporarilyFirstPerson || _actionMovementEnabled == null || !_actionMovementEnabled.Value)
			{
				return false;
			}
			if (!CanAcceptGameplayCameraInput())
			{
				return false;
			}
			if (_actionMovementWhileGrabbing == null || !_actionMovementWhileGrabbing.Value)
			{
				if ((Object)(object)PhysGrabber.instance != (Object)null && PhysGrabber.instance.grabbed)
				{
					return false;
				}
				if ((Object)(object)PlayerController.instance != (Object)null && PlayerController.instance.physGrabActive)
				{
					return false;
				}
			}
			return true;
		}

		private static bool CanAcceptGameplayCameraInput()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			if (!((Object)(object)GameDirector.instance != (Object)null) || (int)GameDirector.instance.currentState != 2)
			{
				return false;
			}
			if (!((Object)(object)PlayerController.instance != (Object)null) || !((Object)(object)PlayerAvatar.instance != (Object)null) || !((Object)(object)CameraAim.Instance != (Object)null))
			{
				return false;
			}
			if ((int)Cursor.lockState != 1)
			{
				return false;
			}
			if (IsAnyMenuPageOpen() || SemiFunc.MenuLevel() || !SemiFunc.NoTextInputsActive())
			{
				return false;
			}
			if ((Object)(object)Map.Instance != (Object)null && Map.Instance.Active)
			{
				return false;
			}
			return true;
		}

		private static bool CanToggleThirdPerson()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			if (!((Object)(object)GameDirector.instance != (Object)null) || (int)GameDirector.instance.currentState != 2)
			{
				return false;
			}
			if (!((Object)(object)PlayerController.instance != (Object)null) || !((Object)(object)PlayerAvatar.instance != (Object)null) || !((Object)(object)CameraAim.Instance != (Object)null))
			{
				return false;
			}
			if (IsAnyMenuPageOpen() || SemiFunc.MenuLevel() || !SemiFunc.NoTextInputsActive())
			{
				return false;
			}
			return true;
		}

		private static bool IsAnyMenuPageOpen()
		{
			MenuManager instance = MenuManager.instance;
			if (!((Object)(object)instance != (Object)null))
			{
				return false;
			}
			if (_menuCurrentPageField == null)
			{
				_menuCurrentPageField = typeof(MenuManager).GetField("currentMenuPage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			object? obj = _menuCurrentPageField?.GetValue(instance);
			Object val = (Object)((obj is Object) ? obj : null);
			if (val != null)
			{
				return val != (Object)null;
			}
			return false;
		}

		private Vector3 ReadCameraRelativeMoveDirection(Transform cameraTransform)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			float num2 = 0f;
			if (IsKeyHeld((KeyCode)119))
			{
				num2 += 1f;
			}
			if (IsKeyHeld((KeyCode)115))
			{
				num2 -= 1f;
			}
			if (IsKeyHeld((KeyCode)100))
			{
				num += 1f;
			}
			if (IsKeyHeld((KeyCode)97))
			{
				num -= 1f;
			}
			if (Mathf.Abs(num) <= 0.001f && Mathf.Abs(num2) <= 0.001f)
			{
				return Vector3.zero;
			}
			return ReadCameraRelativeMoveDirection(cameraTransform, num, num2);
		}

		private static Vector3 ReadGameInputCameraRelativeMoveDirection(Transform cameraTransform)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return ReadCameraRelativeMoveDirection(cameraTransform, SemiFunc.InputMovementX(), SemiFunc.InputMovementY());
		}

		private static Vector3 ReadCameraRelativeMoveDirection(Transform cameraTransform, float horizontal, float vertical)
		{
			//IL_0023: 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_0069: 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_0070: 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_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)
			//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_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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)cameraTransform == (Object)null || (Mathf.Abs(horizontal) <= 0.001f && Mathf.Abs(vertical) <= 0.001f))
			{
				return Vector3.zero;
			}
			Vector3 val = cameraTransform.forward;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
			{
				val = cameraTransform.rotation * Vector3.forward;
				val.y = 0f;
			}
			val = ((Vector3)(ref val)).normalized;
			Vector3 val2 = cameraTransform.right;
			val2.y = 0f;
			if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
			{
				val2 = Vector3.Cross(Vector3.up, val);
			}
			val2 = ((Vector3)(ref val2)).normalized;
			Vector3 result = val * vertical + val2 * horizontal;
			if (((Vector3)(ref result)).sqrMagnitude > 1f)
			{
				result = ((Vector3)(ref result)).normalized;
			}
			return result;
		}

		private Vector3 ReadActionMovementDirectionFromCamera()
		{
			//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_000f: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			CameraAim instance = CameraAim.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return Vector3.zero;
			}
			Vector3 val = ReadCameraRelativeMoveDirection(((Component)instance).transform);
			if (((Vector3)(ref val)).sqrMagnitude >= 0.0001f)
			{
				_lastActionMoveDirection = val;
				_lastActionMoveDirectionTime = Time.time;
			}
			return val;
		}

		private void RotateAvatarTowardMovement(PlayerAvatar avatar, Vector3 moveDirection)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			Transform actionMovementRotationTarget = GetActionMovementRotationTarget(avatar);
			if ((Object)(object)actionMovementRotationTarget != (Object)null)
			{
				RotateTransformToward(actionMovementRotationTarget, moveDirection);
			}
		}

		private void RotateTransformToward(Transform target, Vector3 moveDirection)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			RotateTransformToward(target, moveDirection, Time.deltaTime);
		}

		private void RotateTransformToward(Transform target, Vector3 moveDirection, float deltaTime)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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)
			if (!((Object)(object)target == (Object)null))
			{
				moveDirection.y = 0f;
				if (!(((Vector3)(ref moveDirection)).sqrMagnitude < 0.0001f))
				{
					target.rotation = SmoothedLookRotation(target.rotation, moveDirection, deltaTime);
				}
			}
		}

		private void RotateVisualsTowardMovement(PlayerAvatarVisuals visuals, Vector3 moveDirection, float deltaTime)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)visuals == (Object)null))
			{
				moveDirection.y = 0f;
				if (!(((Vector3)(ref moveDirection)).sqrMagnitude < 0.0001f))
				{
					Quaternion currentRotation = (_hasVisualFacingRotation ? _visualFacingRotation : ((Component)visuals).transform.rotation);
					_visualFacingRotation = SmoothedLookRotation(currentRotation, moveDirection, deltaTime);
					_hasVisualFacingRotation = true;
					ApplyVisualFacingRotation(visuals);
				}
			}
		}

		private void ApplyVisualFacingRotation(PlayerAvatarVisuals visuals)
		{
			//IL_0017: 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)
			if (_hasVisualFacingRotation && !((Object)(object)visuals == (Object)null))
			{
				((Component)visuals).transform.rotation = _visualFacingRotation;
				SetPlayerAvatarVisualsBodySpringTarget(visuals, _visualFacingRotation);
			}
		}

		private void SetPlayerAvatarVisualsBodySpringTarget(PlayerAvatarVisuals visuals, Quaternion rotation)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)visuals == (Object)null))
			{
				if (_avatarVisualBodySpringTargetField == null)
				{
					_avatarVisualBodySpringTargetField = typeof(PlayerAvatarVisuals).GetField("bodySpringTarget", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				_avatarVisualBodySpringTargetField?.SetValue(visuals, rotation);
			}
		}

		private Quaternion SmoothedLookRotation(Quaternion currentRotation, Vector3 moveDirection, float deltaTime)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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)
			moveDirection.y = 0f;
			if (((Vector3)(ref moveDirection)).sqrMagnitude < 0.0001f)
			{
				return currentRotation;
			}
			Quaternion val = Quaternion.LookRotation(((Vector3)(ref moveDirection)).normalized, Vector3.up);
			float num = Mathf.Max(1f, _actionTurnSpeed?.Value ?? 14f);
			float num2 = 1f - Mathf.Exp(0f - num * Mathf.Max(0f, deltaTime));
			return Quaternion.Slerp(currentRotation, val, num2);
		}

		private void StabilizeCachedLocalModdedModel()
		{
			if (_thirdPersonActive && !_temporarilyFirstPerson && !((Object)(object)_cachedModelInstance == (Object)null))
			{
				StabilizeLocalModdedModel(_cachedModelInstance);
			}
		}

		private void StabilizeLocalModdedModel(GameObject model)
		{
			//IL_0017: 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)
			if (!((Object)(object)model == (Object)null))
			{
				model.transform.rotation = GetStableLocalModelRotation(model.transform.rotation);
			}
		}

		private void LockLocalAvatarVisualsToRoot()
		{
			//IL_0045: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			if (!_thirdPersonActive || _temporarilyFirstPerson)
			{
				return;
			}
			PlayerAvatar instance = PlayerAvatar.instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.playerAvatarVisuals == (Object)null) && !IsAvatarDeadOrDisabled(instance))
			{
				PlayerAvatarVisuals playerAvatarVisuals = instance.playerAvatarVisuals;
				Vector3 position = ((Component)instance).transform.position;
				((Component)playerAvatarVisuals).transform.position = position;
				ApplyVisualFacingRotation(playerAvatarVisuals);
				if (_avatarVisualPositionField == null)
				{
					_avatarVisualPositionField = typeof(PlayerAvatarVisuals).GetField("visualPosition", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				if (_avatarVisualFollowLerpField == null)
				{
					_avatarVisualFollowLerpField = typeof(PlayerAvatarVisuals).GetField("visualFollowLerp", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				_avatarVisualPositionField?.SetValue(playerAvatarVisuals, position);
				_avatarVisualFollowLerpField?.SetValue(playerAvatarVisuals, 1f);
			}
		}

		private Quaternion GetStableLocalModelRotation(Quaternion fallbackRotation)
		{
			//IL_0007: 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_003e: 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_0057: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			if (_hasVisualFacingRotation)
			{
				return _visualFacingRotation;
			}
			PlayerController instance = PlayerController.instance;
			if ((Object)(object)instance != (Object)null)
			{
				return ((Component)instance).transform.rotation;
			}
			if (_hasRewriteTurnYaw)
			{
				return Quaternion.Euler(0f, _lastRewriteTurnYaw, 0f);
			}
			if (((Vector3)(ref _lastActionMoveDirection)).sqrMagnitude > 0.0001f)
			{
				return ExactLookRotation(_lastActionMoveDirection, fallbackRotation);
			}
			return fallbackRotation;
		}

		private static Quaternion ExactLookRotation(Vector3 moveDirection, Quaternion fallbackRotation)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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)
			moveDirection.y = 0f;
			if (((Vector3)(ref moveDirection)).sqrMagnitude < 0.0001f)
			{
				return fallbackRotation;
			}
			return Quaternion.LookRotation(((Vector3)(ref moveDirection)).normalized, Vector3.up);
		}

		private Transform GetActionMovementRotationTarget(PlayerAvatar avatar)
		{
			if (!((Object)(object)avatar != (Object)null))
			{
				return null;
			}
			return ((Component)avatar).transform;
		}

		private bool TryGetGameplayAimRotation(out Quaternion rotation)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			rotation = Quaternion.identity;
			if (!_thirdPersonActive || _temporarilyFirstPerson || !CanAcceptGameplayCameraInput())
			{
				return false;
			}
			CameraAim instance = CameraAim.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			Vector3 forward = ((Component)instance).transform.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f)
			{
				return false;
			}
			rotation = Quaternion.LookRotation(((Vector3)(ref forward)).normalized, Vector3.up);
			return true;
		}

		private bool TryGetGameplayAimYaw(out float yaw)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			yaw = 0f;
			if (!TryGetGameplayAimRotation(out var rotation))
			{
				return false;
			}
			yaw = ((Quaternion)(ref rotation)).eulerAngles.y;
			return true;
		}

		private void LateUpdate()
		{
			TickCamera();
			LockLocalAvatarVisualsToRoot();
			StabilizeCachedLocalModdedModel();
		}

		internal void TickCamera()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0089: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			if (_lastCameraTickFrame == Time.frameCount)
			{
				return;
			}
			_lastCameraTickFrame = Time.frameCount;
			HandleLifecycleReset();
			if (!_thirdPersonActive)
			{
				return;
			}
			PlayerAvatar instance = PlayerAvatar.instance;
			CameraAim instance2 = CameraAim.Instance;
			CameraPosition instance3 = CameraPosition.instance;
			if (!((Object)(object)instance != (Object)null) || !((Object)(object)instance2 != (Object)null) || !((Object)(object)instance3 != (Object)null))
			{
				return;
			}
			ApplyThirdPersonCompatibility(active: true);
			if (ShouldTemporarilyUseFirstPerson())
			{
				EnterTemporaryFirstPerson(instance3, instance);
				return;
			}
			_temporarilyFirstPerson = false;
			Vector3 val = CalculateCameraPosition(instance, ((Component)instance2).transform);
			Ray thirdPersonCenterRay = GetThirdPersonCenterRay(val, ((Component)instance2).transform.rotation);
			UpdateSelectionTransform(instance, thirdPersonCenterRay);
			instance3.OverridePosition(val, 0.1f);
			((Component)instance3).transform.position = val;
			if ((Object)(object)instance.playerAvatarVisuals != (Object)null)
			{
				instance.playerAvatarVisuals.ShowSelfOverride(0.15f);
			}
			ApplyClipPlanes();
		}

		private void HandleLifecycleReset()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar instance = PlayerAvatar.instance;
			int num = ((!((Object)(object)GameDirector.instance != (Object)null)) ? (-1) : ((int)GameDirector.instance.currentState));
			if (_lastGameState != num)
			{
				_lastGameState = num;
				if (_thirdPersonActive && num != 2)
				{
					ResetThirdPersonState("game state changed");
					return;
				}
			}
			if (_lastPlayerAvatar != instance)
			{
				_lastPlayerAvatar = instance;
				if (_thirdPersonActive)
				{
					ResetThirdPersonState("local player changed");
					return;
				}
			}
			if (_thirdPersonActive && IsAvatarDeadOrDisabled(instance))
			{
				ResetThirdPersonState("local player died or disabled");
			}
		}

		private bool IsAvatarDeadOrDisabled(PlayerAvatar avatar)
		{
			if ((Object)(object)avatar == (Object)null)
			{
				return true;
			}
			Type type = ((object)avatar).GetType();
			if (_avatarIsDisabledField == null)
			{
				_avatarIsDisabledField = type.GetField("isDisabled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (_avatarDeadSetField == null)
			{
				_avatarDeadSetField = type.GetField("deadSet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			try
			{
				bool flag = default(bool);
				int num;
				if (_avatarIsDisabledField != null)
				{
					object value = _avatarIsDisabledField.GetValue(avatar);
					if (value is bool)
					{
						flag = (bool)value;
						num = 1;
					}
					else
					{
						num = 0;
					}
				}
				else
				{
					num = 0;
				}
				if (((uint)num & (flag ? 1u : 0u)) != 0)
				{
					return true;
				}
				bool flag2 = default(bool);
				int num2;
				if (_avatarDeadSetField != null)
				{
					object value = _avatarDeadSetField.GetValue(avatar);
					if (value is bool)
					{
						flag2 = (bool)value;
						num2 = 1;
					}
					else
					{
						num2 = 0;
					}
				}
				else
				{
					num2 = 0;
				}
				if (((uint)num2 & (flag2 ? 1u : 0u)) != 0)
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private void ResetThirdPersonState(string reason)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			if (_thirdPersonActive)
			{
				_thirdPersonActive = false;
				_temporarilyFirstPerson = false;
				_currentDistance = ClampDistance(_defaultDistance.Value);
				ApplyThirdPersonCompatibility(active: false);
				CameraPosition instance = CameraPosition.instance;
				if ((Object)(object)instance != (Object)null && (Object)(object)instance.playerTransform != (Object)null)
				{
					instance.OverridePosition(Vector3.zero, 0f);
				}
				PlayerAvatar instance2 = PlayerAvatar.instance;
				if ((Object)(object)instance2 != (Object)null && (Object)(object)instance2.playerAvatarVisuals != (Object)null)
				{
					instance2.playerAvatarVisuals.ShowSelfOverride(0f);
				}
				RestoreClipPlanes();
				_lastActionMoveDirection = Vector3.zero;
				_lastActionMoveDirectionTime = 0f;
				_hasRewriteTurnYaw = false;
				_hasVisualFacingRotation = false;
				RestoreLocalModelMotionVectors();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Third-person camera reset: " + reason + "."));
			}
		}

		private void OnDisable()
		{
			SetThirdPersonActive(active: false);
		}

		private void OnDestroy()
		{
			//IL_0053: 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_0063: Expected O, but got Unknown
			//IL_0063: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			SetThirdPersonActive(active: false);
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			DisposeInputActions();
			if ((Object)(object)_selectionTransform != (Object)null)
			{
				Object.Destroy((Object)((Component)_selectionTransform).gameObject);
				_selectionTransform = null;
			}
			if ((Object)Instance == (Object)this)
			{
				Instance = null;
			}
		}

		private void SetThirdPersonActive(bool active)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if (_thirdPersonActive == active)
			{
				return;
			}
			_thirdPersonActive = active;
			if (active)
			{
				_currentDistance = ClampDistance(_defaultDistance.Value);
				_hasVisualFacingRotation = false;
				ApplyClipPlanes();
				ApplyThirdPersonCompatibility(active: true);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Third-person camera enabled.");
				return;
			}
			ApplyThirdPersonCompatibility(active: false);
			_hasVisualFacingRotation = false;
			CameraPosition instance = CameraPosition.instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance.playerTransform != (Object)null)
			{
				instance.OverridePosition(Vector3.zero, 0f);
			}
			PlayerAvatar instance2 = PlayerAvatar.instance;
			if ((Object)(object)instance2 != (Object)null && (Object)(object)instance2.playerAvatarVisuals != (Object)null)
			{
				instance2.playerAvatarVisuals.ShowSelfOverride(0f);
			}
			RestoreClipPlanes();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Third-person camera disabled.");
		}

		private static bool ShouldTemporarilyUseFirstPerson()
		{
			if ((Object)(object)Map.Instance != (Object)null)
			{
				return Map.Instance.Active;
			}
			return false;
		}

		private void EnterTemporaryFirstPerson(CameraPosition cameraPosition, PlayerAvatar avatar)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!_temporarilyFirstPerson)
			{
				_temporarilyFirstPerson = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Map/tablet active; temporarily using first-person camera.");
			}
			if ((Object)(object)cameraPosition != (Object)null && (Object)(object)cameraPosition.playerTransform != (Object)null)
			{
				cameraPosition.OverridePosition(Vector3.zero, 0f);
			}
			if ((Object)(object)avatar != (Object)null && (Object)(object)avatar.playerAvatarVisuals != (Object)null)
			{
				avatar.playerAvatarVisuals.ShowSelfOverride(0f);
			}
		}

		private void ApplyThirdPersonCompatibility(bool active)
		{
			_localModdedModelVisible = false;
			if (_forceLocalModdedModel == null || !_forceLocalModdedModel.Value)
			{
				return;
			}
			if (!EnsureModdedModelCompatibilityCached())
			{
				if (active && !_loggedModelCompatibilityMissing)
				{
					_loggedModelCompatibilityMissing = true;
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not find ModdedModelPlayerAvatar.ForceShowLocalModel yet; local model compatibility will retry occasionally while third-person is active.");
				}
				return;
			}
			_forceShowLocalModelField?.SetValue(null, active);
			if (active)
			{
				_localModdedModelVisible = ForceVisibleLocalModdedModel(PlayerAvatar.instance);
				return;
			}
			_cachedModelAvatar = null;
			_cachedModelComponent = null;
			_cachedModelInstance = null;
			_cachedForcedRenderers = null;
			_localModdedModelVisible = false;
		}

		private bool ForceVisibleLocalModdedModel(PlayerAvatar avatar)
		{
			if (_forceLocalModdedModel == null || !_forceLocalModdedModel.Value || !_thirdPersonActive || _temporarilyFirstPerson || !((Object)(object)avatar != (Object)null))
			{
				return false;
			}
			if (!EnsureModdedModelCompatibilityCached())
			{
				return false;
			}
			_forceShowLocalModelField?.SetValue(null, true);
			if (_cachedModelAvatar != avatar || (Object)(object)_cachedModelComponent == (Object)null)
			{
				_cachedModelAvatar = avatar;
				_cachedModelComponent = ((Component)avatar).GetComponent(_moddedModelPlayerAvatarType) ?? ((Component)avatar).GetComponentInChildren(_moddedModelPlayerAvatarType, true);
				_cachedModelInstance = null;
				_cachedForcedRenderers = null;
			}
			Component cachedModelComponent = _cachedModelComponent;
			if (!((Object)(object)cachedModelComponent != (Object)null))
			{
				return false;
			}
			object? obj = _currentModelInstanceField?.GetValue(cachedModelComponent);
			GameObject val = (GameObject)((obj is GameObject) ? obj : null);
			if (!((Object)(object)val != (Object)null) && _applyModelToVisualMethod != null && (Object)(object)avatar.playerAvatarVisuals != (Object)null && Time.time >= _nextModelCompatibilityRetryTime)
			{
				_nextModelCompatibilityRetryTime = Time.time + 1f;
				try
				{
					_applyModelToVisualMethod.Invoke(cachedModelComponent, new object[1] { avatar.playerAvatarVisuals });
					object? obj2 = _currentModelInstanceField?.GetValue(cachedModelComponent);
					val = (GameObject)((obj2 is GameObject) ? obj2 : null);
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[ThirdPersonCompat] ApplyModelToVisual failed: " + ex.Message));
				}
			}
			if (!((Object)(object)val != (Object)null))
			{
				return false;
			}
			val.SetActive(true);
			if (_cachedModelInstance != val)
			{
				_cachedModelInstance = val;
				List<Renderer> list = new List<Renderer>();
				if (_cachedModelRenderersField?.GetValue(cachedModelComponent) is IEnumerable enumerable)
				{
					foreach (object item in enumerable)
					{
						Renderer val2 = (Renderer)((item is Renderer) ? item : null);
						if (val2 != null && (Object)(object)val2 != (Object)null)
						{
							list.Add(val2);
						}
					}
				}
				if (list.Count == 0)
				{
					list.AddRange(val.GetComponentsInChildren<Renderer>(true));
				}
				_cachedForcedRenderers = list.ToArray();
				_nextRendererRefreshTime = 0f;
			}
			if (_cachedForcedRenderers != null && Time.time >= _nextRendererRefreshTime)
			{
				_nextRendererRefreshTime = Time.time + 0.5f;
				Renderer[] cachedForcedRenderers = _cachedForcedRenderers;
				foreach (Renderer val3 in cachedForcedRenderers)
				{
					if ((Object)(object)val3 != (Object)null)
					{
						val3.enabled = true;
					}
				}
				ApplyLocalVisibleModelRendererCompatibility(_cachedForcedRenderers);
			}
			if (!_loggedModelCompatibility)
			{
				_loggedModelCompatibility = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Forced local ModdedModelPlayerAvatar model visible for third-person camera.");
			}
			return true;
		}

		private void ApplyNoMotionVectorsToAvatarVisuals(PlayerAvatarVisuals visuals)
		{
		}

		private void ApplyLocalVisibleModelRendererCompatibility(IEnumerable<Renderer> renderers)
		{
		}

		private void RestoreLocalModelMotionVectors()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyValuePair<Renderer, MotionVectorGenerationMode> originalRendererMotionVector in _originalRendererMotionVectors)
			{
				if ((Object)(object)originalRendererMotionVector.Key != (Object)null)
				{
					originalRendererMotionVector.Key.motionVectorGenerationMode = originalRendererMotionVector.Value;
				}
			}
			_originalRendererMotionVectors.Clear();
			foreach (KeyValuePair<GameObject, int> originalRendererLayer in _originalRendererLayers)
			{
				if ((Object)(object)originalRendererLayer.Key != (Object)null)
				{
					originalRendererLayer.Key.layer = originalRendererLayer.Value;
				}
			}
			_originalRendererLayers.Clear();
			_cachedAvatarVisualsForMotionVectors = null;
			_cachedAvatarVisualRenderers = null;
			_nextAvatarRendererRefreshTime = 0f;
		}

		private void ApplyThirdPersonMotionBlurOverride(bool active)
		{
			if (!active)
			{
				RestoreThirdPersonMotionBlurOverride();
			}
		}

		private void RestoreThirdPersonMotionBlurOverride()
		{
			if (_motionBlurOverrideActive)
			{
				MotionBlur postProcessingMotionBlur = GetPostProcessingMotionBlur();
				if ((Object)(object)postProcessingMotionBlur != (Object)null)
				{
					((ParameterOverride<float>)(object)postProcessingMotionBlur.shutterAngle).value = _motionBlurOriginalShutterAngle;
					((PostProcessEffectSettings)postProcessingMotionBlur).active = _motionBlurOriginalActive;
				}
				_motionBlurOverrideActive = false;
			}
		}

		private MotionBlur GetPostProcessingMotionBlur()
		{
			PostProcessing instance = PostProcessing.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			if (_postProcessingMotionBlurField == null)
			{
				_postProcessingMotionBlurField = typeof(PostProcessing).GetField("motionBlur", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			object? obj = _postProcessingMotionBlurField?.GetValue(instance);
			return (MotionBlur)((obj is MotionBlur) ? obj : null);
		}

		private bool EnsureModdedModelCompatibilityCached()
		{
			if (_moddedModelPlayerAvatarType != null)
			{
				return true;
			}
			if (Time.time < _nextModelCompatibilityRetryTime)
			{
				return false;
			}
			_nextModelCompatibilityRetryTime = Time.time + 1f;
			_moddedModelPlayerAvatarType = FindLoadedType("ModdedModelPlayerAvatar");
			if (_moddedModelPlayerAvatarType == null || !typeof(Component).IsAssignableFrom(_moddedModelPlayerAvatarType))
			{
				_moddedModelPlayerAvatarType = null;
				return false;
			}
			_forceShowLocalModelField = _moddedModelPlayerAvatarType.GetField("ForceShowLocalModel", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			_currentModelInstanceField = _moddedModelPlayerAvatarType.GetField("currentModelInstance", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			_cachedModelRenderersField = _moddedModelPlayerAvatarType.GetField("_cachedModelRenderers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			_applyModelToVisualMethod = _moddedModelPlayerAvatarType.GetMethod("ApplyModelToVisual", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			TryPatchModdedModelUpdate();
			return _forceShowLocalModelField != null;
		}

		private void TryPatchModdedModelUpdate()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			if (_moddedModelUpdatePatched || _harmony == null || _moddedModelPlayerAvatarType == null)
			{
				return;
			}
			MethodInfo method = _moddedModelPlayerAvatarType.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			MethodInfo method2 = typeof(RepoUpdatePatches).GetMethod("ModdedModelPlayerAvatarUpdatePostfix", BindingFlags.Static | BindingFlags.NonPublic);
			if (method == null || method2 == null)
			{
				return;
			}
			try
			{
				HarmonyMethod val = new HarmonyMethod(method2);
				val.priority = 0;
				_harmony.Patch((MethodBase)method, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_moddedModelUpdatePatched = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Patched ModdedModelPlayerAvatar.Update for action-movement facing.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[ThirdPersonCompat] Failed to patch ModdedModelPlayerAvatar.Update: " + ex.Message));
			}
		}

		private static bool SetKnownStaticBool(string typeName, string fieldName, bool value)
		{
			Type type = FindLoadedType(typeName);
			if (type == null)
			{
				return false;
			}
			FieldInfo field = type.GetField(fieldName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && field.FieldType == typeof(bool))
			{
				field.SetValue(null, value);
				return true;
			}
			return false;
		}

		private static Type FindLoadedType(string typeName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type type = assembly.GetType(typeName);
				if (type != null)
				{
					return type;
				}
				try
				{
					Type[] types = assembly.GetTypes();
					foreach (Type type2 in types)
					{
						if (type2.Name == typeName)
						{
							return type2;
						}
					}
				}
				catch (ReflectionTypeLoadException ex)
				{
					Type[] types = ex.Types;
					foreach (Type type3 in types)
					{
						if (type3 != null && type3.Name == typeName)
						{
							return type3;
						}
					}
				}
			}
			return null;
		}

		private void HandleZoomInput()
		{
			//IL_004a: 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)
			if (CanAcceptZoomInput())
			{
				float num = ReadScrollWheel();
				if (Mathf.Abs(num) > 0.001f)
				{
					_currentDistance -= num * _scrollSensitivity.Value;
				}
				if (IsActionHeld(_zoomInAction) || IsKeyHeld(_zoomInKey.Value))
				{
					_currentDistance -= _keyZoomSpeed.Value * Time.deltaTime;
				}
				if (IsActionHeld(_zoomOutAction) || IsKeyHeld(_zoomOutKey.Value))
				{
					_currentDistance += _keyZoomSpeed.Value * Time.deltaTime;
				}
				_currentDistance = ClampDistance(_currentDistance);
			}
		}

		private void HandleOffsetInput()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (!CanAcceptOffsetInput())
			{
				return;
			}
			if (IsKeyPressedThisFrame(_resetOffsetsKey.Value))
			{
				_runtimeOffsetX = _startingOffsetX;
				_runtimeOffsetY = _startingOffsetY;
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Camera offsets reset to X={_runtimeOffsetX:0.###}, Y={_runtimeOffsetY:0.###}.");
				return;
			}
			float num = _offsetAdjustSpeed.Value * Time.deltaTime;
			if (!(num <= 0f))
			{
				if (IsKeyHeld((KeyCode)276))
				{
					_runtimeOffsetX -= num;
				}
				if (IsKeyHeld((KeyCode)275))
				{
					_runtimeOffsetX += num;
				}
				if (IsKeyHeld((KeyCode)273))
				{
					_runtimeOffsetY += num;
				}
				if (IsKeyHeld((KeyCode)274))
				{
					_runtimeOffsetY -= num;
				}
			}
		}

		private static bool CanAcceptZoomInput()
		{
			if (!CanAcceptGameplayCameraInput())
			{
				return false;
			}
			if ((Object)(object)PhysGrabber.instance != (Object)null && PhysGrabber.instance.grabbed)
			{
				return false;
			}
			if ((Object)(object)PlayerController.instance != (Object)null && PlayerController.instance.physGrabActive)
			{
				return false;
			}
			return true;
		}

		private static bool CanAcceptOffsetInput()
		{
			return CanAcceptGameplayCameraInput();
		}

		private Vector3 CalculateCameraPosition(PlayerAvatar avatar, Transform aimTransform)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_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_004f: 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)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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)
			//IL_0070: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)avatar).transform.position + Vector3.up * _runtimeOffsetY + aimTransform.right * _runtimeOffsetX;
			Vector3 val2 = val - aimTransform.forward * _currentDistance;
			Vector3 val3 = val2 - val;
			float magnitude = ((Vector3)(ref val3)).magnitude;
			if (magnitude <= 0.001f)
			{
				return val;
			}
			val3 /= magnitude;
			int num = ((_collisionMask != 0) ? _collisionMask : LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct()));
			RaycastHit val4 = default(RaycastHit);
			if (Physics.SphereCast(val, _collisionRadius.Value, val3, ref val4, magnitude, num, (QueryTriggerInteraction)1))
			{
				float num2 = Mathf.Max(0f, ((RaycastHit)(ref val4)).distance - _collisionPadding.Value);
				return val + val3 * num2;
			}
			return val2;
		}

		private static Ray GetThirdPersonCenterRay(Vector3 origin, Quaternion fallbackRotation)
		{
			//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_003f: 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_001f: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			if ((Object)(object)main != (Object)null)
			{
				Ray val = main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f));
				return new Ray(origin, ((Ray)(ref val)).direction);
			}
			return new Ray(origin, fallbackRotation * Vector3.forward);
		}

		private void UpdateSelectionTransform(PlayerAvatar avatar, Ray cameraCenterRay)
		{
			//IL_005c: 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_0044: 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_0061: 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_0069: 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_0074: 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_0085: 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)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00bf: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_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_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)
			if ((Object)(object)_selectionTransform != (Object)null && (Object)(object)avatar != (Object)null)
			{
				Transform val = avatar.PlayerVisionTarget?.VisionTransform;
				Vector3 val2 = (((Object)(object)val != (Object)null) ? val.position : (((Component)avatar).transform.position + Vector3.up * _runtimeOffsetY));
				Vector3 direction = ((Ray)(ref cameraCenterRay)).direction;
				Vector3 normalized = ((Vector3)(ref direction)).normalized;
				Vector3 val3 = ((Ray)(ref cameraCenterRay)).origin + normalized * _selectionMaxDistance.Value;
				int mask = LayerMask.GetMask(new string[1] { "Player" });
				int num = LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct()) - mask;
				RaycastHit val4 = default(RaycastHit);
				if (Physics.Raycast(((Ray)(ref cameraCenterRay)).origin, normalized, ref val4, _selectionMaxDistance.Value, num, (QueryTriggerInteraction)1))
				{
					val3 = ((RaycastHit)(ref val4)).point;
				}
				Vector3 val5 = val3 - val2;
				if (((Vector3)(ref val5)).sqrMagnitude < 0.0001f)
				{
					val5 = normalized;
				}
				_selectionTransform.position = val2;
				_selectionTransform.rotation = Quaternion.LookRotation(((Vector3)(ref val5)).normalized, Vector3.up);
			}
		}

		internal bool TryGetSelectionOverride(PlayerLocalCamera localCamera, ref Transform result)
		{
			if (!CanOverrideSelection(localCamera))
			{
				return false;
			}
			result = _selectionTransform;
			return true;
		}

		private bool CanOverrideSelection(PlayerLocalCamera localCamera)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0052: Expected O, but got Unknown
			if (!_thirdPersonActive || !_cameraCenteredSelection.Value || _temporarilyFirstPerson)
			{
				return false;
			}
			if (!((Object)(object)_selectionTransform != (Object)null) || !((Object)(object)localCamera != (Object)null))
			{
				return false;
			}
			return (Object)localCamera.playerAvatar == (Object)PlayerAvatar.instance;
		}

		private float ClampDistance(float distance)
		{
			float num = Mathf.Max(0.1f, _minDistance?.Value ?? 1f);
			float num2 = Mathf.Max(num, _maxDistance?.Value ?? 10f);
			return Mathf.Clamp(distance, num, num2);
		}

		private void ApplyClipPlanes()
		{
			CollectCameras();
			foreach (Camera item in _cameraBuffer)
			{
				if ((Object)(object)item != (Object)null)
				{
					if (!_originalClipPlanes.ContainsKey(item))
					{
						_originalClipPlanes.Add(item, new ClipPlaneState
						{
							Near = item.nearClipPlane,
							Far = item.farClipPlane
						});
					}
					ClipPlaneState clipPlaneState = _originalClipPlanes[item];
					item.nearClipPlane = Mathf.Min(clipPlaneState.Near, _nearClipPlane.Value);
					item.farClipPlane = Mathf.Max(clipPlaneState.Far, _minimumFarClipPlane.Value);
				}
			}
		}

		private void RestoreClipPlanes()
		{
			foreach (KeyValuePair<Camera, ClipPlaneState> originalClipPlane in _originalClipPlanes)
			{
				Camera key = originalClipPlane.Key;
				if ((Object)(object)key != (Object)null)
				{
					key.nearClipPlane = originalClipPlane.Value.Near;
					key.farClipPlane = originalClipPlane.Value.Far;
				}
			}
			_originalClipPlanes.Clear();
			_cameraBuffer.Clear();
		}

		private void CollectCameras()
		{
			_cameraBuffer.Clear();
			AddCamera(Camera.main);
			Camera[] allCameras = Camera.allCameras;
			for (int i = 0; i < allCameras.Length; i++)
			{
				AddCamera(allCameras[i]);
			}
			CameraZoom instance = CameraZoom.Instance;
			if (instance?.cams == null)
			{
				return;
			}
			foreach (Camera cam in instance.cams)
			{
				AddCamera(cam);
			}
		}

		private void AddCamera(Camera cam)
		{
			if ((Object)(object)cam != (Object)null && !cam.orthographic && !_cameraBuffer.Contains(cam))
			{
				_cameraBuffer.Add(cam);
			}
		}

		private void CreateInputActions()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			DisposeInputActions();
			_toggleAction = CreateKeyboardAction("REPO Native Third Person Toggle", _toggleKey.Value);
			_zoomInAction = CreateKeyboardAction("REPO Native Third Person Zoom In", _zoomInKey.Value);
			_zoomOutAction = CreateKeyboardAction("REPO Native Third Person Zoom Out", _zoomOutKey.Value);
		}

		private static InputAction CreateKeyboardAction(string name, KeyCode keyCode)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0023: Expected O, but got Unknown
			string text = KeyCodeToKeyboardPath(keyCode);
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			InputAction val = new InputAction(name, (InputActionType)1, text, (string)null, (string)null, (string)null);
			val.Enable();
			return val;
		}

		private void DisposeInputActions()
		{
			DisposeInputAction(ref _toggleAction);
			DisposeInputAction(ref _zoomInAction);
			DisposeInputAction(ref _zoomOutAction);
		}

		private static void DisposeInputAction(ref InputAction action)
		{
			if (action != null)
			{
				action.Disable();
				action.Dispose();
				action = null;
			}
		}

		private static bool IsActionPressedThisFrame(InputAction action)
		{
			if (action != null && action.enabled)
			{
				return action.WasPressedThisFrame();
			}
			return false;
		}

		private static bool IsActionHeld(InputAction action)
		{
			if (action != null && action.enabled)
			{
				return action.IsPressed();
			}
			return false;
		}

		private static bool IsKeyPressedThisFrame(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return Input.GetKeyDown(key);
			}
			catch
			{
				return false;
			}
		}

		private static bool IsKeyHeld(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return Input.GetKey(key);
			}
			catch
			{
				return false;
			}
		}

		private static float ReadScrollWheel()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)InputManager.instance != (Object)null)
			{
				float scrollY = InputManager.instance.GetScrollY();
				if (Mathf.Abs(scrollY) > 0.001f)
				{
					return Mathf.Sign(scrollY);
				}
			}
			if (Mouse.current != null)
			{
				float y = ((InputControl<Vector2>)(object)Mouse.current.scroll).ReadValue().y;
				if (Mathf.Abs(y) > 0.001f)
				{
					return Mathf.Sign(y);
				}
			}
			try
			{
				return Input.mouseScrollDelta.y;
			}
			catch
			{
				return 0f;
			}
		}

		private static bool TryGetKeyboardKey(KeyCode keyCode, out Key key)
		{
			key = (Key)0;
			return false;
		}

		private static string KeyCodeToKeyboardPath(KeyCode keyCode)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Expected I4, but got Unknown
			int num = (int)keyCode;
			if (num >= 97 && num <= 122)
			{
				return $"<Keyboard>/{(char)num}";
			}
			if (num >= 48 && num <= 57)
			{
				return $"<Keyboard>/{num - 48}";
			}
			if (num >= 256 && num <= 265)
			{
				return $"<Keyboard>/numpad{num - 256}";
			}
			switch (num)
			{
			case 8:
				return "<Keyboard>/backspace";
			case 9:
				return "<Keyboard>/tab";
			case 13:
				return "<Keyboard>/enter";
			case 27:
				return "<Keyboard>/escape";
			case 32:
				return "<Keyboard>/space";
			case 43:
			case 61:
				return "<Keyboard>/equals";
			case 45:
				return "<Keyboard>/minus";
			case 127:
				return "<Keyboard>/delete";
			case 273:
				return "<Keyboard>/upArrow";
			case 274:
				return "<Keyboard>/downArrow";
			case 275:
				return "<Keyboard>/rightArrow";
			case 276:
				return "<Keyboard>/leftArrow";
			case 277:
				return "<Keyboard>/insert";
			case 278:
				return "<Keyboard>/home";
			case 279:
				return "<Keyboard>/end";
			case 280:
				return "<Keyboard>/pageUp";
			case 281:
				return "<Keyboard>/pageDown";
			default:
				if (num >= 282 && num <= 293)
				{
					return $"<Keyboard>/f{num - 281}";
				}
				return null;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[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;
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}