Decompiled source of AskaFirstPerson v1.0.4

BepInEx\plugins\AskaFirstPerson\AskaFirstPerson.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Fusion;
using HarmonyLib;
using HarmonyLib.Tools;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AskaFirstPerson
{
	[HarmonyPatch("Cinemachine.CinemachineBrain", "LateUpdate")]
	public static class CinemachineBrainPatch
	{
		[HarmonyPrefix]
		public static bool Prefix()
		{
			return !FirstPersonBehaviour.IsFirstPerson;
		}
	}
	public class FirstPersonBehaviour : MonoBehaviour
	{
		public static bool IsFirstPerson;

		internal static string SuppressedToggleButtonName;

		internal static bool ChordModifierIsHeld;

		internal static bool InSelfRead;

		private Camera _cam;

		private Transform _headBone;

		private Transform _playerRoot;

		private Transform _characterRoot;

		private Transform _skeletonRoot;

		private Transform _leftHand;

		private Transform _rightHand;

		private Transform _spine;

		private Transform _spine1;

		private Gamepad _gamepad;

		private float _pitch;

		private float _yaw;

		private float _savedFOV;

		private float _savedNearClip;

		private Vector3 _smoothVelocity;

		private Vector3 _stableBasePos;

		private readonly List<Renderer> _shadowOnlyRenderers = new List<Renderer>();

		private float _rendererScanTimer;

		private const float RendererScanInterval = 0.5f;

		private static readonly string[] LowerBodyPrefixes = new string[6] { "ragnar_base_forearm", "ragnar_base_hand", "ragnar_base_pants", "ragnar_base_boots", "ragnar_base_belt", "ragnar_base_glove" };

		private void Update()
		{
			//IL_004d: 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_0096: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			if (!IsInGameplay())
			{
				if (IsFirstPerson)
				{
					IsFirstPerson = false;
					DisableFirstPerson();
					ClearCachedReferences();
					FirstPersonPlugin.Log.LogInfo((object)"Left gameplay — first-person auto-disabled");
				}
				return;
			}
			try
			{
				_gamepad = Gamepad.current;
			}
			catch
			{
				_gamepad = null;
			}
			if (Input.GetKeyDown(FirstPersonPlugin.CfgToggleKey.Value) || TryReadGamepadToggle())
			{
				IsFirstPerson = !IsFirstPerson;
				if (IsFirstPerson)
				{
					EnableFirstPerson();
				}
				else
				{
					DisableFirstPerson();
				}
				ManualLogSource log = FirstPersonPlugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(19, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("First-person mode: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(IsFirstPerson ? "ON" : "OFF");
				}
				log.LogInfo(val);
			}
			if (!IsFirstPerson || (Object)(object)_cam == (Object)null || IsGamePaused())
			{
				return;
			}
			float value = FirstPersonPlugin.CfgSensitivity.Value;
			_yaw += Input.GetAxis("Mouse X") * value;
			_pitch -= Input.GetAxis("Mouse Y") * value;
			if (_gamepad != null)
			{
				try
				{
					Vector2 val2 = ((InputControl<Vector2>)(object)_gamepad.rightStick).ReadValue();
					float num = value * 3f;
					_yaw += val2.x * num * Time.deltaTime * 60f;
					_pitch -= val2.y * num * Time.deltaTime * 60f;
				}
				catch
				{
				}
			}
			_pitch = Mathf.Clamp(_pitch, -89f, 89f);
		}

		private bool TryReadGamepadToggle()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (_gamepad == null)
			{
				ResetSuppressionState();
				return false;
			}
			try
			{
				InSelfRead = true;
				try
				{
					string value = FirstPersonPlugin.CfgGamepadToggleButton.Value;
					ButtonControl gamepadButton = GetGamepadButton(_gamepad, value);
					string value2 = FirstPersonPlugin.CfgGamepadModifierButton.Value;
					bool flag = string.Equals(value2, "None", StringComparison.OrdinalIgnoreCase);
					bool flag2 = false;
					if (!flag)
					{
						ButtonControl gamepadButton2 = GetGamepadButton(_gamepad, value2);
						flag2 = gamepadButton2 != null && gamepadButton2.isPressed;
					}
					bool chordModifierIsHeld = ChordModifierIsHeld;
					SuppressedToggleButtonName = ((flag || gamepadButton == null) ? null : ((InputControl)gamepadButton).name);
					ChordModifierIsHeld = flag2;
					if (chordModifierIsHeld != flag2)
					{
						InputSuppressionPatch.LoggedMagnitudeThisHold = false;
					}
					if (flag2 && gamepadButton != null)
					{
						try
						{
							InputState.Change<float>((InputControl)(object)gamepadButton, 0f, (InputUpdateType)0, default(InputEventPtr));
						}
						catch
						{
						}
					}
					return gamepadButton != null && gamepadButton.wasPressedThisFrame && (flag || flag2);
				}
				finally
				{
					InSelfRead = false;
				}
			}
			catch
			{
				return false;
			}
		}

		private static void ResetSuppressionState()
		{
			SuppressedToggleButtonName = null;
			ChordModifierIsHeld = false;
			InputSuppressionPatch.LoggedMagnitudeThisHold = false;
		}

		private void LateUpdate()
		{
			//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_004e: 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)
			//IL_0069: 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_00c6: 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_00db: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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_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_0136: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			if (!IsFirstPerson)
			{
				return;
			}
			if ((Object)(object)_cam == (Object)null || (Object)(object)_headBone == (Object)null)
			{
				TryFindReferences();
			}
			else
			{
				if (IsGamePaused())
				{
					return;
				}
				float deltaTime = Time.deltaTime;
				if (deltaTime <= 0f)
				{
					return;
				}
				Vector3 position = _headBone.position;
				if (!IsFinite(position))
				{
					return;
				}
				float value = FirstPersonPlugin.CfgMotionDampening.Value;
				float x = position.x;
				float z = position.z;
				float y = position.y;
				float num = Mathf.Lerp(30f, 6f, value);
				_stableBasePos.y = Mathf.Lerp(_stableBasePos.y, y, deltaTime * num);
				float num2 = Mathf.Lerp(y, _stableBasePos.y, value);
				Vector3 val = new Vector3(x, num2, z);
				Vector3 forward = ((Component)_cam).transform.forward;
				Vector3 val2 = val + Vector3.up * FirstPersonPlugin.CfgVerticalOffset.Value + forward * FirstPersonPlugin.CfgForwardOffset.Value;
				Vector3 val3 = Vector3.SmoothDamp(((Component)_cam).transform.position, val2, ref _smoothVelocity, 1f / FirstPersonPlugin.CfgSmoothSpeed.Value);
				if (IsFinite(val3))
				{
					((Component)_cam).transform.position = val3;
				}
				else
				{
					_smoothVelocity = Vector3.zero;
				}
				((Component)_cam).transform.rotation = Quaternion.Euler(_pitch, _yaw, 0f);
				if ((Object)(object)_spine != (Object)null && (Object)(object)_playerRoot != (Object)null)
				{
					float num3 = Mathf.Clamp(Mathf.DeltaAngle(_playerRoot.eulerAngles.y, _yaw), -80f, 80f) * 0.5f;
					_spine.localRotation *= Quaternion.Euler(0f, num3, 0f);
					if ((Object)(object)_spine1 != (Object)null)
					{
						_spine1.localRotation *= Quaternion.Euler(0f, num3, 0f);
					}
				}
				_rendererScanTimer += Time.deltaTime;
				if (_rendererScanTimer >= 0.5f)
				{
					_rendererScanTimer = 0f;
					HidePlayerRenderers(rebuildCache: false);
				}
			}
		}

		private void EnableFirstPerson()
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_00a9: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			TryFindReferences();
			if ((Object)(object)_cam == (Object)null)
			{
				FirstPersonPlugin.Log.LogWarning((object)"Cannot enable first-person — main camera not found. Ensure you are in-game (not a loading screen).");
				IsFirstPerson = false;
				return;
			}
			_savedFOV = _cam.fieldOfView;
			_savedNearClip = _cam.nearClipPlane;
			_cam.fieldOfView = FirstPersonPlugin.CfgFOV.Value;
			_cam.nearClipPlane = FirstPersonPlugin.CfgNearClip.Value;
			Vector3 eulerAngles = ((Component)_cam).transform.eulerAngles;
			_yaw = eulerAngles.y;
			_pitch = ((eulerAngles.x > 180f) ? (eulerAngles.x - 360f) : eulerAngles.x);
			_stableBasePos = (((Object)(object)_headBone != (Object)null) ? _headBone.position : ((Component)_cam).transform.position);
			if ((Object)(object)_headBone != (Object)null && (Object)(object)_playerRoot != (Object)null)
			{
				float y = _playerRoot.position.y;
				float y2 = _headBone.position.y;
				ManualLogSource log = FirstPersonPlugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(73, 5, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Diagnostics] PlayerRoot Y=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(y, "F2");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", HeadBone Y=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(y2, "F2");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", ");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("HeadHeight=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(y2 - y, "F2");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", Camera Y=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(((Component)_cam).transform.position.y, "F2");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", ");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Player=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)_playerRoot).name);
				}
				log.LogInfo(val);
			}
			HidePlayerRenderers(rebuildCache: true);
		}

		private void DisableFirstPerson()
		{
			if ((Object)(object)_cam != (Object)null)
			{
				_cam.fieldOfView = _savedFOV;
				_cam.nearClipPlane = _savedNearClip;
			}
			ShowPlayerModel();
		}

		private void TryFindReferences()
		{
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			if ((Object)(object)_cam == (Object)null)
			{
				_cam = Camera.main;
			}
			bool flag = default(bool);
			if ((Object)(object)_playerRoot == (Object)null)
			{
				GameObject val = FindLocalPlayer();
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				_playerRoot = val.transform;
				Transform val2 = _playerRoot.Find("GeometryParent");
				BepInExInfoLogInterpolatedStringHandler val4;
				if ((Object)(object)val2 != (Object)null)
				{
					for (int i = 0; i < val2.childCount; i++)
					{
						Transform child = val2.GetChild(i);
						Transform val3 = child.Find("master");
						if ((Object)(object)val3 != (Object)null)
						{
							_characterRoot = child;
							_skeletonRoot = val3;
							ManualLogSource log = FirstPersonPlugin.Log;
							val4 = new BepInExInfoLogInterpolatedStringHandler(37, 2, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Character geometry root: ");
								((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)child).name);
								((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(", skeleton: ");
								((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)val3).name);
							}
							log.LogInfo(val4);
							break;
						}
					}
				}
				ManualLogSource log2 = FirstPersonPlugin.Log;
				val4 = new BepInExInfoLogInterpolatedStringHandler(14, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Local player: ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)val).name);
				}
				log2.LogInfo(val4);
			}
			if (!((Object)(object)_skeletonRoot != (Object)null))
			{
				return;
			}
			if ((Object)(object)_headBone == (Object)null)
			{
				_headBone = _skeletonRoot.Find("Bip001/Bip001 Pelvis/Bip001 Spine/Bip001 Spine1/Bip001 Neck/Bip001 Head");
				if ((Object)(object)_headBone != (Object)null)
				{
					ManualLogSource log3 = FirstPersonPlugin.Log;
					BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(20, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Head bone resolved: ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)_headBone).name);
					}
					log3.LogInfo(val4);
				}
				else
				{
					FirstPersonPlugin.Log.LogWarning((object)"Could not find head bone via explicit path. The skeleton hierarchy may have changed.");
				}
			}
			if ((Object)(object)_leftHand == (Object)null)
			{
				_leftHand = _skeletonRoot.Find("Bip001/Bip001 Pelvis/Bip001 Spine/Bip001 Spine1/Bip001 L Clavicle/Bip001 L UpperArm/Bip001 L Forearm/Bip001 L Hand");
			}
			if ((Object)(object)_rightHand == (Object)null)
			{
				_rightHand = _skeletonRoot.Find("Bip001/Bip001 Pelvis/Bip001 Spine/Bip001 Spine1/Bip001 R Clavicle/Bip001 R UpperArm/Bip001 R Forearm/Bip001 R Hand");
			}
			if ((Object)(object)_spine == (Object)null)
			{
				_spine = _skeletonRoot.Find("Bip001/Bip001 Pelvis/Bip001 Spine");
			}
			if ((Object)(object)_spine1 == (Object)null)
			{
				_spine1 = _skeletonRoot.Find("Bip001/Bip001 Pelvis/Bip001 Spine/Bip001 Spine1");
			}
		}

		private static bool IsLowerBody(string name)
		{
			string[] lowerBodyPrefixes = LowerBodyPrefixes;
			foreach (string value in lowerBodyPrefixes)
			{
				if (name.StartsWith(value, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsChildOf(Transform t, Transform ancestor)
		{
			if ((Object)(object)ancestor == (Object)null)
			{
				return false;
			}
			Transform parent = t.parent;
			while ((Object)(object)parent != (Object)null)
			{
				if ((Object)(object)parent == (Object)(object)ancestor)
				{
					return true;
				}
				parent = parent.parent;
			}
			return false;
		}

		private void HidePlayerRenderers(bool rebuildCache)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Invalid comparison between Unknown and I4
			if ((Object)(object)_playerRoot == (Object)null)
			{
				return;
			}
			if (rebuildCache)
			{
				_shadowOnlyRenderers.Clear();
			}
			bool value = FirstPersonPlugin.CfgShowBody.Value;
			Renderer[] array;
			try
			{
				array = Il2CppArrayBase<Renderer>.op_Implicit(((Component)_playerRoot).GetComponentsInChildren<Renderer>());
			}
			catch
			{
				return;
			}
			if (array == null)
			{
				return;
			}
			Renderer[] array2 = array;
			foreach (Renderer val in array2)
			{
				try
				{
					if (!((Object)(object)val == (Object)null) && val.enabled && (int)val.shadowCastingMode != 3 && !IsChildOf(((Component)val).transform, _leftHand) && !IsChildOf(((Component)val).transform, _rightHand) && (!value || !((Object)(object)_characterRoot != (Object)null) || !((Object)(object)((Component)val).transform.parent == (Object)(object)_characterRoot) || !IsLowerBody(((Object)((Component)val).gameObject).name)))
					{
						val.shadowCastingMode = (ShadowCastingMode)3;
						_shadowOnlyRenderers.Add(val);
					}
				}
				catch
				{
				}
			}
			if (!rebuildCache && _shadowOnlyRenderers.Count > 0)
			{
				_shadowOnlyRenderers.RemoveAll((Renderer r) => (Object)(object)r == (Object)null);
			}
			if (rebuildCache)
			{
				FirstPersonPlugin.Log.LogInfo((object)($"Set {_shadowOnlyRenderers.Count} renderers to shadow-only " + "(body + equipment + accessories; hands kept visible)"));
			}
		}

		private void ShowPlayerModel()
		{
			foreach (Renderer shadowOnlyRenderer in _shadowOnlyRenderers)
			{
				try
				{
					if ((Object)(object)shadowOnlyRenderer != (Object)null)
					{
						shadowOnlyRenderer.shadowCastingMode = (ShadowCastingMode)1;
					}
				}
				catch
				{
				}
			}
			_shadowOnlyRenderers.Clear();
		}

		private GameObject FindLocalPlayer()
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			Il2CppReferenceArray<GameObject> val = GameObject.FindGameObjectsWithTag("Player");
			if (val == null || ((Il2CppArrayBase<GameObject>)(object)val).Length == 0)
			{
				return null;
			}
			if (((Il2CppArrayBase<GameObject>)(object)val).Length == 1)
			{
				return ((Il2CppArrayBase<GameObject>)(object)val)[0];
			}
			try
			{
				foreach (GameObject item in (Il2CppArrayBase<GameObject>)(object)val)
				{
					NetworkObject component = item.GetComponent<NetworkObject>();
					if ((Object)(object)component != (Object)null && component.HasInputAuthority)
					{
						return item;
					}
				}
			}
			catch
			{
			}
			if ((Object)(object)_cam == (Object)null)
			{
				_cam = Camera.main;
			}
			if ((Object)(object)_cam == (Object)null)
			{
				return ((Il2CppArrayBase<GameObject>)(object)val)[0];
			}
			GameObject result = null;
			float num = float.MaxValue;
			foreach (GameObject item2 in (Il2CppArrayBase<GameObject>)(object)val)
			{
				float num2 = Vector3.Distance(item2.transform.position, ((Component)_cam).transform.position);
				if (num2 < num)
				{
					num = num2;
					result = item2;
				}
			}
			return result;
		}

		private static bool IsInGameplay()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			return ((Scene)(ref activeScene)).name == "StreamingWorld";
		}

		private void ClearCachedReferences()
		{
			_cam = null;
			_headBone = null;
			_playerRoot = null;
			_characterRoot = null;
			_skeletonRoot = null;
			_leftHand = null;
			_rightHand = null;
			_spine = null;
			_spine1 = null;
			ResetSuppressionState();
		}

		private static bool IsGamePaused()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			if (Time.timeScale == 0f)
			{
				return true;
			}
			if (Cursor.visible || (int)Cursor.lockState != 1)
			{
				return true;
			}
			return false;
		}

		private static bool IsFinite(Vector3 v)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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)
			if (!float.IsNaN(v.x) && !float.IsNaN(v.y) && !float.IsNaN(v.z) && !float.IsInfinity(v.x) && !float.IsInfinity(v.y))
			{
				return !float.IsInfinity(v.z);
			}
			return false;
		}

		private static ButtonControl GetGamepadButton(Gamepad pad, string name)
		{
			switch (name)
			{
			case "North":
			case "ButtonNorth":
				return pad.buttonNorth;
			case "South":
			case "ButtonSouth":
				return pad.buttonSouth;
			case "East":
			case "ButtonEast":
				return pad.buttonEast;
			case "West":
			case "ButtonWest":
				return pad.buttonWest;
			case "LeftBumper":
			case "LeftShoulder":
				return pad.leftShoulder;
			case "RightBumper":
			case "RightShoulder":
				return pad.rightShoulder;
			case "LeftTrigger":
				return pad.leftTrigger;
			case "RightTrigger":
				return pad.rightTrigger;
			case "LeftStickButton":
				return pad.leftStickButton;
			case "RightStickButton":
				return pad.rightStickButton;
			case "Start":
			case "StartButton":
				return pad.startButton;
			case "SelectButton":
			case "Select":
				return pad.selectButton;
			case "DpadUp":
				return pad.dpad.up;
			case "DpadDown":
				return pad.dpad.down;
			case "DpadLeft":
				return pad.dpad.left;
			case "DpadRight":
				return pad.dpad.right;
			default:
				return null;
			}
		}
	}
	[BepInPlugin("com.community.askafirstperson", "Aska First Person Camera", "1.0.4")]
	public class FirstPersonPlugin : BasePlugin
	{
		public const string PluginGuid = "com.community.askafirstperson";

		public const string PluginName = "Aska First Person Camera";

		public const string PluginVersion = "1.0.4";

		internal static ManualLogSource Log;

		public static ConfigEntry<float> CfgFOV;

		public static ConfigEntry<float> CfgSensitivity;

		public static ConfigEntry<float> CfgNearClip;

		public static ConfigEntry<float> CfgVerticalOffset;

		public static ConfigEntry<float> CfgForwardOffset;

		public static ConfigEntry<float> CfgSmoothSpeed;

		public static ConfigEntry<float> CfgMotionDampening;

		public static ConfigEntry<bool> CfgShowBody;

		public static ConfigEntry<KeyCode> CfgToggleKey;

		public static ConfigEntry<string> CfgGamepadToggleButton;

		public static ConfigEntry<string> CfgGamepadModifierButton;

		public static ConfigEntry<bool> CfgSafeMode;

		public static ConfigEntry<bool> CfgEnableCinemachinePatch;

		public static ConfigEntry<bool> CfgEnableInputSuppressionPatch;

		public static ConfigEntry<bool> CfgEnableBehaviour;

		private bool _initialized;

		private UnityAction<Scene, LoadSceneMode> _sceneLoadedHandler;

		public override void Load()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Expected O, but got Unknown
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Expected O, but got Unknown
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BasePlugin)this).Log;
			CfgFOV = ((BasePlugin)this).Config.Bind<float>("Camera", "FOV", 80f, new ConfigDescription("First-person field of view", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 120f), Array.Empty<object>()));
			CfgSensitivity = ((BasePlugin)this).Config.Bind<float>("Camera", "MouseSensitivity", 2f, new ConfigDescription("Mouse look sensitivity", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
			CfgNearClip = ((BasePlugin)this).Config.Bind<float>("Camera", "NearClipPlane", 0.05f, "Near clip plane distance — lower values prevent seeing inside geometry");
			CfgVerticalOffset = ((BasePlugin)this).Config.Bind<float>("Camera", "VerticalOffset", 0.1f, "Vertical offset above the head bone (metres)");
			CfgForwardOffset = ((BasePlugin)this).Config.Bind<float>("Camera", "ForwardOffset", 0.12f, "Forward offset from the head bone (metres)");
			CfgSmoothSpeed = ((BasePlugin)this).Config.Bind<float>("Camera", "SmoothSpeed", 15f, new ConfigDescription("Position smoothing factor — higher = less smoothing", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
			CfgMotionDampening = ((BasePlugin)this).Config.Bind<float>("Camera", "MotionDampening", 0.4f, new ConfigDescription("Reduces vertical camera shake from combat, rolls, and head bob. Only affects up/down movement — lateral tracking stays responsive. 0 = no dampening (raw head tracking), 1 = maximum dampening. Recommended 0.3-0.5.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			CfgShowBody = ((BasePlugin)this).Config.Bind<bool>("Visibility", "ShowLowerBody", false, "Show lower body (forearms, hands, legs) in first-person. Off = cleaner look (shadow-only body, weapons visible). On = see arms/legs but may have visual artifacts (mesh seams, backface culling).");
			CfgToggleKey = ((BasePlugin)this).Config.Bind<KeyCode>("Controls", "ToggleKey", (KeyCode)286, "Key to toggle between first-person and third-person camera");
			CfgGamepadToggleButton = ((BasePlugin)this).Config.Bind<string>("Controls", "GamepadToggleButton", "RightStickButton", "Gamepad button to toggle first-person mode. Valid: North, South, East, West, LeftShoulder, RightShoulder, LeftTrigger, RightTrigger, LeftStickButton, RightStickButton, Start, Select, DpadUp, DpadDown, DpadLeft, DpadRight");
			CfgGamepadModifierButton = ((BasePlugin)this).Config.Bind<string>("Controls", "GamepadModifierButton", "LeftShoulder", "Modifier button that must be held while pressing the toggle button. Set to \"None\" to disable the modifier (bare button press). Default: LeftShoulder (LB + R3 chord avoids conflicting with game actions). Valid: None, North, South, East, West, LeftShoulder, RightShoulder, LeftTrigger, RightTrigger, LeftStickButton, RightStickButton, Start, Select, DpadUp, DpadDown, DpadLeft, DpadRight");
			CfgSafeMode = ((BasePlugin)this).Config.Bind<bool>("General", "SafeMode", false, "Skip ALL Harmony patches and the MonoBehaviour. The plugin loads inert. Use this if the mod is crashing the game at startup — leave it installed while you collect logs without losing your config.");
			CfgEnableCinemachinePatch = ((BasePlugin)this).Config.Bind<bool>("Advanced", "EnableCinemachinePatch", true, "Apply the CinemachineBrain.LateUpdate prefix that suppresses Cinemachine while first-person is active. Disabling this disables first-person camera control.");
			CfgEnableInputSuppressionPatch = ((BasePlugin)this).Config.Bind<bool>("Advanced", "EnableInputSuppressionPatch", true, "Apply the InputControl.EvaluateMagnitude postfix that hides the chord toggle button from the game while the modifier is held. Disabling this means the gamepad toggle button will still trigger its normal in-game action.");
			CfgEnableBehaviour = ((BasePlugin)this).Config.Bind<bool>("Advanced", "EnableBehaviour", true, "Register the FirstPersonBehaviour MonoBehaviour. Disabling this stops the mod from doing any per-frame work even if patches are active.");
			LogEnvironment();
			bool flag = default(bool);
			if (CfgSafeMode.Value)
			{
				ManualLogSource log = Log;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(71, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Aska First Person Camera");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" v");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.4");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" SAFE MODE — skipping Harmony patches and behaviour. Plugin is inert.");
				}
				log.LogWarning(val);
				return;
			}
			_sceneLoadedHandler = UnityAction<Scene, LoadSceneMode>.op_Implicit((Action<Scene, LoadSceneMode>)OnSceneLoaded);
			SceneManager.sceneLoaded += _sceneLoadedHandler;
			string value = CfgGamepadModifierButton.Value;
			string value2 = CfgGamepadToggleButton.Value;
			string text = (string.Equals(value, "None", StringComparison.OrdinalIgnoreCase) ? value2 : (value + "+" + value2));
			ManualLogSource log2 = Log;
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(79, 4, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("Aska First Person Camera");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" v");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.0.4");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded (deferred mode) — waiting for StreamingWorld; toggle [");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<KeyCode>(CfgToggleKey.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] or gamepad [");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("]");
			}
			log2.LogInfo(val2);
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			if (_initialized)
			{
				return;
			}
			string text;
			try
			{
				Scene activeScene = SceneManager.GetActiveScene();
				text = ((Scene)(ref activeScene)).name;
			}
			catch
			{
				text = string.Empty;
			}
			if (((Scene)(ref scene)).name != "StreamingWorld" && text != "StreamingWorld")
			{
				return;
			}
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(72, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Scene observed: loaded='");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Scene)(ref scene)).name);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' active='");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' — initializing first-person systems.");
			}
			log.LogInfo(val);
			try
			{
				InitializeFirstPersonSystems();
				_initialized = true;
				if ((Delegate)(object)_sceneLoadedHandler != (Delegate)null)
				{
					SceneManager.sceneLoaded -= _sceneLoadedHandler;
					_sceneLoadedHandler = null;
				}
				Log.LogInfo((object)"First-person systems initialized; sceneLoaded handler detached.");
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Log;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(32, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Deferred initialization threw ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.GetType().Name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				log2.LogError(val2);
			}
		}

		private void InitializeFirstPersonSystems()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0011: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			Harmony harmony = new Harmony("com.community.askafirstperson");
			List<string> list = new List<string>();
			LogChannel channelFilter = Logger.ChannelFilter;
			Logger.ChannelFilter = (LogChannel)(channelFilter & -9);
			try
			{
				if (CfgEnableCinemachinePatch.Value)
				{
					if (PreflightValidate("Cinemachine.CinemachineBrain", "LateUpdate", Type.EmptyTypes, typeof(void)) && TryPatchClass(harmony, typeof(CinemachineBrainPatch)))
					{
						list.Add("Cinemachine");
					}
				}
				else
				{
					Log.LogWarning((object)"EnableCinemachinePatch=false — skipping Cinemachine patch (first-person camera will not work).");
				}
				if (CfgEnableInputSuppressionPatch.Value)
				{
					if (PreflightValidate("UnityEngine.InputSystem.InputControl", "EvaluateMagnitude", Type.EmptyTypes, typeof(float)))
					{
						(string, Type)[] patchClasses = InputSuppressionPatch.PatchClasses;
						for (int i = 0; i < patchClasses.Length; i++)
						{
							var (item, type) = patchClasses[i];
							if (TryPatchClass(harmony, type))
							{
								list.Add(item);
							}
						}
					}
				}
				else
				{
					Log.LogWarning((object)"EnableInputSuppressionPatch=false — skipping InputControl.EvaluateMagnitude patch (gamepad toggle button will still trigger its normal in-game action).");
				}
			}
			finally
			{
				Logger.ChannelFilter = channelFilter;
			}
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(26, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Harmony patches active: [");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", list));
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("]");
			}
			log.LogInfo(val);
			if (CfgEnableBehaviour.Value)
			{
				((BasePlugin)this).AddComponent<FirstPersonBehaviour>();
			}
			else
			{
				Log.LogWarning((object)"EnableBehaviour=false — FirstPersonBehaviour not registered; mod will not run per-frame logic.");
			}
		}

		private static bool TryPatchClass(Harmony harmony, Type type)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			try
			{
				harmony.CreateClassProcessor(type).Patch();
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(25, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Skipping Harmony patch ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(type.Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				log.LogWarning(val);
				return false;
			}
		}

		private static void LogEnvironment()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				ManualLogSource log = Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(22, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Env: process=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>((IntPtr.Size == 8) ? "x64" : "x86");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" runtime=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Version>(Environment.Version);
				}
				log.LogInfo(val);
				ManualLogSource log2 = Log;
				val = new BepInExInfoLogInterpolatedStringHandler(16, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Env: plugin DLL=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Assembly.GetExecutingAssembly().Location);
				}
				log2.LogInfo(val);
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(35, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Env dump (process/runtime) failed: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				log3.LogWarning(val2);
			}
			try
			{
				ManualLogSource log4 = Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Env: Unity=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Application.unityVersion);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" game=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Application.productName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" v=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Application.version);
				}
				log4.LogInfo(val);
			}
			catch (Exception ex2)
			{
				ManualLogSource log5 = Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(37, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Env dump (Unity/Application) failed: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex2.Message);
				}
				log5.LogWarning(val2);
			}
			DumpInteropAssembly("Cinemachine.CinemachineBrain");
			DumpInteropAssembly("UnityEngine.InputSystem.InputControl");
			DumpInteropAssembly("UnityEngine.Camera");
		}

		private static void DumpInteropAssembly(string typeName)
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				Type type = AccessTools.TypeByName(typeName);
				BepInExInfoLogInterpolatedStringHandler val;
				if (type == null)
				{
					ManualLogSource log = Log;
					val = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Env: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(typeName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" -> TYPE NOT FOUND");
					}
					log.LogInfo(val);
					return;
				}
				Assembly assembly = type.Assembly;
				AssemblyInformationalVersionAttribute customAttribute = assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
				ManualLogSource log2 = Log;
				val = new BepInExInfoLogInterpolatedStringHandler(19, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Env: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(typeName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" asm=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(assembly.GetName().Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" v=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Version>(assembly.GetName().Version);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" info=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(customAttribute?.InformationalVersion);
				}
				log2.LogInfo(val);
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(19, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Env: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(typeName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" dump failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				log3.LogInfo(val);
			}
		}

		private static bool PreflightValidate(string typeName, string methodName, Type[] argTypes, Type expectedReturn)
		{
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Expected O, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			bool flag2 = default(bool);
			try
			{
				Type type = AccessTools.TypeByName(typeName);
				if (type == null)
				{
					ManualLogSource log = Log;
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(45, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Pre-flight: type ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(typeName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" not found — skipping patch.");
					}
					log.LogWarning(val);
					return false;
				}
				MethodInfo methodInfo = AccessTools.Method(type, methodName, argTypes, (Type[])null);
				if (methodInfo == null)
				{
					ManualLogSource log2 = Log;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(48, 3, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Pre-flight: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(typeName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(methodName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("(");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(argTypes.Length);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" args) not found — skipping patch.");
					}
					log2.LogWarning(val);
					return false;
				}
				if (expectedReturn != null && methodInfo.ReturnType != expectedReturn)
				{
					ManualLogSource log3 = Log;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(51, 4, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Pre-flight: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(typeName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(methodName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" returns ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(methodInfo.ReturnType.FullName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", expected ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(expectedReturn.FullName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" — skipping patch.");
					}
					log3.LogWarning(val);
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource log4 = Log;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(51, 4, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Pre-flight: validating ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(typeName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(methodName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" threw ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.GetType().Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" — skipping patch.");
				}
				log4.LogWarning(val);
				return false;
			}
		}
	}
	internal static class InputSuppressionPatch
	{
		[HarmonyPatch("UnityEngine.InputSystem.InputControl", "EvaluateMagnitude")]
		[HarmonyPatch(new Type[] { })]
		public static class EvaluateMagnitudePatch
		{
			[HarmonyPostfix]
			public static void Postfix(InputControl __instance, ref float __result)
			{
				if (!(__result <= 0f) && ShouldSuppressControl(__instance))
				{
					__result = 0f;
					LogOnce(ref LoggedMagnitudeThisHold, "Magnitude", "InputControl.EvaluateMagnitude(" + __instance.name + ") -> 0");
				}
			}
		}

		internal static bool LoggedMagnitudeThisHold;

		internal static readonly (string Layer, Type PatchClass)[] PatchClasses = new(string, Type)[1] { ("Magnitude", typeof(EvaluateMagnitudePatch)) };

		private static bool ShouldSuppressControl(InputControl instance)
		{
			if (instance == null)
			{
				return false;
			}
			if (FirstPersonBehaviour.InSelfRead)
			{
				return false;
			}
			if (!FirstPersonBehaviour.ChordModifierIsHeld)
			{
				return false;
			}
			string suppressedToggleButtonName = FirstPersonBehaviour.SuppressedToggleButtonName;
			if (string.IsNullOrEmpty(suppressedToggleButtonName))
			{
				return false;
			}
			try
			{
				return string.Equals(instance.name, suppressedToggleButtonName, StringComparison.Ordinal);
			}
			catch
			{
				return false;
			}
		}

		private static void LogOnce(ref bool latch, string layerTag, string detail)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			if (latch)
			{
				return;
			}
			latch = true;
			try
			{
				ManualLogSource log = FirstPersonPlugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(12, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Suppress.");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(layerTag);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(detail);
				}
				log.LogInfo(val);
			}
			catch
			{
			}
		}
	}
}