Decompiled source of NativeController v0.6.0

NativeController.dll

Decompiled 6 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using MenuLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[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("NativeController")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.6.0.0")]
[assembly: AssemblyInformationalVersion("0.6.0+2074cbac6ea40b26f02c830fd79b13635a80bf22")]
[assembly: AssemblyProduct("NativeController")]
[assembly: AssemblyTitle("NativeController")]
[assembly: AssemblyVersion("0.6.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NativeController
{
	internal class AimAssist : MonoBehaviour
	{
		internal static bool HasTarget;

		internal static Vector3 TargetPosition;

		private const float CastRadius = 0.4f;

		private const float LosMargin = 0.5f;

		private const float AcquireFraction = 0.6f;

		private const float SwitchMarginDeg = 4f;

		private const float MinDwellSeconds = 0.15f;

		private const float PointSmoothTime = 0.08f;

		private static readonly FieldRef<PhysGrabber, PhysGrabObject> GrabbedRef = AccessTools.FieldRefAccess<PhysGrabber, PhysGrabObject>("grabbedPhysGrabObject");

		private static readonly FieldRef<EnemyParent, Enemy> EnemyRef = AccessTools.FieldRefAccess<EnemyParent, Enemy>("Enemy");

		private static readonly FieldRef<EnemyParent, bool> SpawnedRef = AccessTools.FieldRefAccess<EnemyParent, bool>("Spawned");

		private int _itemMask;

		private int _losMask;

		private bool _masksReady;

		private GameObject _lastTarget;

		private float _dwellTimer;

		private Vector3 _smoothedPoint;

		private Vector3 _pointVel;

		private void Update()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled.Value || !Plugin.AimAssistEnabled.Value)
			{
				Forget();
				return;
			}
			CameraAim instance = CameraAim.Instance;
			Camera main = Camera.main;
			if ((Object)(object)instance == (Object)null || (Object)(object)main == (Object)null)
			{
				Forget();
				return;
			}
			EnsureMasks();
			if (_dwellTimer > 0f)
			{
				_dwellTimer -= Time.deltaTime;
			}
			Vector3 position = ((Component)main).transform.position;
			Vector3 forward = ((Component)main).transform.forward;
			if ((!Plugin.AimAssistEnemies.Value || !IsArmed() || !TryFindEnemy(position, forward, out var pos, out var go)) && (!Plugin.AimAssistItems.Value || !TryFindItem(position, forward, out pos, out go)))
			{
				Forget();
				return;
			}
			if ((Object)(object)go != (Object)(object)_lastTarget)
			{
				_lastTarget = go;
				_smoothedPoint = pos;
				_pointVel = Vector3.zero;
				_dwellTimer = 0.15f;
				Plugin.Log.LogDebug((object)("[AimAssist] target -> " + ((Object)go).name));
			}
			else
			{
				_smoothedPoint = Vector3.SmoothDamp(_smoothedPoint, pos, ref _pointVel, 0.08f);
			}
			TargetPosition = _smoothedPoint;
			HasTarget = true;
		}

		private void OnDisable()
		{
			Forget();
		}

		private void Forget()
		{
			HasTarget = false;
			if ((Object)(object)_lastTarget != (Object)null)
			{
				_lastTarget = null;
				Plugin.Log.LogDebug((object)"[AimAssist] target -> none");
			}
		}

		private static bool IsArmed()
		{
			PhysGrabber instance = PhysGrabber.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			PhysGrabObject val = GrabbedRef.Invoke(instance);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			GameObject gameObject = ((Component)val).gameObject;
			if (!((Object)(object)gameObject.GetComponentInChildren<ItemGun>() != (Object)null) && !((Object)(object)gameObject.GetComponentInChildren<ItemMelee>() != (Object)null))
			{
				return (Object)(object)gameObject.GetComponentInChildren<ValuableWizardStaff>() != (Object)null;
			}
			return true;
		}

		private bool TryFindEnemy(Vector3 origin, Vector3 fwd, out Vector3 pos, out GameObject go)
		{
			//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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: 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)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: 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_0140: Unknown result type (might be due to invalid IL or missing references)
			pos = Vector3.zero;
			go = null;
			EnemyDirector instance = EnemyDirector.instance;
			if ((Object)(object)instance == (Object)null || instance.enemiesSpawned == null)
			{
				return false;
			}
			float value = Plugin.AimAssistMaxAngle.Value;
			float num = value * 0.6f;
			float value2 = Plugin.AimAssistEnemyRange.Value;
			GameObject bestGo = null;
			float num2 = value;
			Vector3 bestPos = Vector3.zero;
			GameObject curGo = null;
			float curAngle = value;
			Vector3 curPos = Vector3.zero;
			foreach (EnemyParent item in instance.enemiesSpawned)
			{
				if ((Object)(object)item == (Object)null || !SpawnedRef.Invoke(item))
				{
					continue;
				}
				Enemy val = EnemyRef.Invoke(item);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Transform val2 = (((Object)(object)val.CenterTransform != (Object)null) ? val.CenterTransform : ((Component)val).transform);
				GameObject gameObject = ((Component)val).gameObject;
				float maxAngle = (((Object)(object)gameObject == (Object)(object)_lastTarget) ? value : num);
				if (Passes(origin, fwd, val2.position, value2, maxAngle, out var angle))
				{
					if ((Object)(object)gameObject == (Object)(object)_lastTarget)
					{
						curGo = gameObject;
						curAngle = angle;
						curPos = val2.position;
					}
					if (angle < num2)
					{
						num2 = angle;
						bestGo = gameObject;
						bestPos = val2.position;
					}
				}
			}
			return Resolve(bestGo, num2, bestPos, curGo, curAngle, curPos, out pos, out go);
		}

		private bool TryFindItem(Vector3 origin, Vector3 fwd, out Vector3 pos, out GameObject go)
		{
			//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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
			pos = Vector3.zero;
			go = null;
			float value = Plugin.AimAssistMaxAngle.Value;
			float num = value * 0.6f;
			float value2 = Plugin.AimAssistItemRange.Value;
			RaycastHit[] array = Physics.SphereCastAll(origin, 0.4f, fwd, value2, _itemMask, (QueryTriggerInteraction)2);
			GameObject bestGo = null;
			float num2 = value;
			Vector3 bestPos = Vector3.zero;
			GameObject curGo = null;
			float curAngle = value;
			Vector3 curPos = Vector3.zero;
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val = array2[i];
				if (!((Component)((RaycastHit)(ref val)).collider).CompareTag("Phys Grab Object"))
				{
					continue;
				}
				PhysGrabObject componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<PhysGrabObject>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					continue;
				}
				GameObject gameObject = ((Component)componentInParent).gameObject;
				Vector3 centerPoint = componentInParent.centerPoint;
				float maxAngle = (((Object)(object)gameObject == (Object)(object)_lastTarget) ? value : num);
				if (Passes(origin, fwd, centerPoint, value2, maxAngle, out var angle))
				{
					if ((Object)(object)gameObject == (Object)(object)_lastTarget)
					{
						curGo = gameObject;
						curAngle = angle;
						curPos = centerPoint;
					}
					if (angle < num2)
					{
						num2 = angle;
						bestGo = gameObject;
						bestPos = centerPoint;
					}
				}
			}
			return Resolve(bestGo, num2, bestPos, curGo, curAngle, curPos, out pos, out go);
		}

		private bool Resolve(GameObject bestGo, float bestAngle, Vector3 bestPos, GameObject curGo, float curAngle, Vector3 curPos, out Vector3 pos, out GameObject go)
		{
			//IL_003e: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)curGo != (Object)null && ((Object)(object)bestGo == (Object)(object)curGo || _dwellTimer > 0f || bestAngle > curAngle - 4f))
			{
				pos = curPos;
				go = curGo;
				return true;
			}
			pos = bestPos;
			go = bestGo;
			return (Object)(object)go != (Object)null;
		}

		private bool Passes(Vector3 origin, Vector3 fwd, Vector3 target, float range, float maxAngle, out float angle)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003a: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			angle = 999f;
			Vector3 val = target - origin;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.05f || magnitude > range)
			{
				return false;
			}
			angle = Vector3.Angle(fwd, val);
			if (angle > maxAngle)
			{
				return false;
			}
			if (Physics.Raycast(origin, val / magnitude, magnitude - 0.5f, _losMask))
			{
				return false;
			}
			return true;
		}

		private void EnsureMasks()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (!_masksReady)
			{
				_itemMask = (_losMask = LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct())) & ~LayerMask.GetMask(new string[1] { "Player" });
				_masksReady = true;
			}
		}
	}
	internal static class ButtonNames
	{
		internal enum Control
		{
			South,
			East,
			West,
			North,
			LB,
			RB,
			LT,
			RT,
			L3,
			R3,
			DpadLeft,
			DpadUp,
			DpadRight,
			DpadDown,
			Start,
			Select,
			LStick,
			RStick
		}

		internal static string Of(Control c, ControllerDetect.Kind kind)
		{
			return kind switch
			{
				ControllerDetect.Kind.PlayStation => Ps(c), 
				ControllerDetect.Kind.Switch => Sw(c), 
				_ => Xbox(c), 
			};
		}

		private static string Xbox(Control c)
		{
			return c switch
			{
				Control.South => "A", 
				Control.East => "B", 
				Control.West => "X", 
				Control.North => "Y", 
				Control.LB => "LB", 
				Control.RB => "RB", 
				Control.LT => "LT", 
				Control.RT => "RT", 
				Control.L3 => "L3", 
				Control.R3 => "R3", 
				Control.DpadLeft => "←", 
				Control.DpadUp => "↑", 
				Control.DpadRight => "→", 
				Control.DpadDown => "↓", 
				Control.Start => "Menu", 
				Control.Select => "View", 
				Control.LStick => "L-Stick", 
				Control.RStick => "R-Stick", 
				_ => "?", 
			};
		}

		private static string Ps(Control c)
		{
			return c switch
			{
				Control.South => "✕", 
				Control.East => "○", 
				Control.West => "□", 
				Control.North => "△", 
				Control.LB => "L1", 
				Control.RB => "R1", 
				Control.LT => "L2", 
				Control.RT => "R2", 
				Control.L3 => "L3", 
				Control.R3 => "R3", 
				Control.DpadLeft => "←", 
				Control.DpadUp => "↑", 
				Control.DpadRight => "→", 
				Control.DpadDown => "↓", 
				Control.Start => "Options", 
				Control.Select => "Create", 
				Control.LStick => "L-Stick", 
				Control.RStick => "R-Stick", 
				_ => "?", 
			};
		}

		private static string Sw(Control c)
		{
			return c switch
			{
				Control.South => "B", 
				Control.East => "A", 
				Control.West => "Y", 
				Control.North => "X", 
				Control.LB => "L", 
				Control.RB => "R", 
				Control.LT => "ZL", 
				Control.RT => "ZR", 
				Control.L3 => "L3", 
				Control.R3 => "R3", 
				Control.DpadLeft => "←", 
				Control.DpadUp => "↑", 
				Control.DpadRight => "→", 
				Control.DpadDown => "↓", 
				Control.Start => "+", 
				Control.Select => "-", 
				Control.LStick => "L-Stick", 
				Control.RStick => "R-Stick", 
				_ => "?", 
			};
		}
	}
	internal class ChatKeyboard : MonoBehaviour
	{
		private static readonly FieldRef<ChatManager, bool> ChatActiveRef = AccessTools.FieldRefAccess<ChatManager, bool>("chatActive");

		private static readonly FieldRef<ChatManager, string> ChatMessageRef = AccessTools.FieldRefAccess<ChatManager, string>("chatMessage");

		private static readonly FieldRef<ChatManager, List<string>> ChatHistoryRef = AccessTools.FieldRefAccess<ChatManager, List<string>>("chatHistory");

		private static readonly FieldRef<ChatManager, int> ChatHistoryIndexRef = AccessTools.FieldRefAccess<ChatManager, int>("chatHistoryIndex");

		private static readonly Action<ChatManager, ChatState> StateSet = AccessTools.MethodDelegate<Action<ChatManager, ChatState>>(AccessTools.Method(typeof(ChatManager), "StateSet", (Type[])null, (Type[])null), (object)null, true);

		internal static bool Open;

		internal static float PanelTop;

		private const int MaxChatLength = 50;

		private const float PadOpenWindow = 0.25f;

		private const float FlickFire = 0.6f;

		private const float FlickRearm = 0.3f;

		private readonly PadKeyboardCore _core = new PadKeyboardCore(hasSpace: true, "SEND", "CLOSE");

		private bool _selectArmed;

		private float _lastSelectPress = -10f;

		private bool _prevChatActive;

		private bool _flickArmed;

		private static bool _warned;

		private void Awake()
		{
			_core.OnChar = TypeChar;
			_core.OnConfirm = SendOrClose;
			_core.OnClose = Cancel;
		}

		internal static void ResetState()
		{
			Open = false;
			PanelTop = 0f;
		}

		private void Update()
		{
			ChatManager instance = ChatManager.instance;
			Gamepad current = Gamepad.current;
			if ((Object)(object)instance == (Object)null || !Plugin.Enabled.Value || !Plugin.ChatKeyboardEnabled.Value)
			{
				Open = false;
				return;
			}
			bool flag;
			try
			{
				flag = ChatActiveRef.Invoke(instance);
			}
			catch (Exception e)
			{
				WarnOnce(e);
				Open = false;
				return;
			}
			if (current != null && current.selectButton.wasPressedThisFrame)
			{
				_lastSelectPress = Time.unscaledTime;
			}
			if (!flag)
			{
				Open = false;
				_prevChatActive = false;
				return;
			}
			if (!_prevChatActive)
			{
				_prevChatActive = true;
				if (current != null && Time.unscaledTime - _lastSelectPress < 0.25f)
				{
					Open = true;
					PanelTop = 0f;
					_core.Reset();
					_selectArmed = false;
					_flickArmed = false;
				}
			}
			if (!Open || current == null)
			{
				return;
			}
			if (!current.selectButton.isPressed && !current.selectButton.wasReleasedThisFrame)
			{
				_selectArmed = true;
			}
			try
			{
				_core.HandleInput(current);
				HandleHistoryFlick(current, instance);
				if (_selectArmed && current.selectButton.wasReleasedThisFrame)
				{
					Cancel();
				}
			}
			catch (Exception e2)
			{
				WarnOnce(e2);
			}
		}

		private void TypeChar(string s)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			ChatManager instance = ChatManager.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if ((ChatMessageRef.Invoke(instance) ?? "").Length >= 50)
				{
					((SemiUI)ChatUI.instance).SemiUITextFlashColor(Color.red, 0.2f);
					((SemiUI)ChatUI.instance).SemiUISpringShakeX(10f, 10f, 0.3f);
					((SemiUI)ChatUI.instance).SemiUISpringScale(0.05f, 5f, 0.2f);
					MenuManager.instance.MenuEffectClick((MenuClickEffectType)2, (MenuPage)null, 1f, 1f, true);
				}
				else
				{
					instance.AddLetterToChat(s);
					((SemiUI)ChatUI.instance).SemiUITextFlashColor(Color.yellow, 0.2f);
					((SemiUI)ChatUI.instance).SemiUISpringShakeY(2f, 5f, 0.2f);
					MenuManager.instance.MenuEffectClick((MenuClickEffectType)4, (MenuPage)null, 2f, 0.2f, true);
				}
			}
		}

		private void HandleHistoryFlick(Gamepad gp, ChatManager chat)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (chat.StateIsActive() && Plugin.ChatHistoryRecallEnabled.Value)
			{
				float y = ((InputControl<Vector2>)(object)gp.rightStick).ReadValue().y;
				if (Mathf.Abs(y) < Mathf.Max(0.3f, Plugin.StickDeadzone.Value))
				{
					_flickArmed = true;
				}
				else if (_flickArmed && !(Mathf.Abs(y) < 0.6f))
				{
					_flickArmed = false;
					HistoryStep(chat, y > 0f);
				}
			}
		}

		private void HistoryStep(ChatManager chat, bool older)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = ChatHistoryRef.Invoke(chat);
			if (list == null || list.Count == 0)
			{
				return;
			}
			ref int reference = ref ChatHistoryIndexRef.Invoke(chat);
			if (older)
			{
				if (reference > 0)
				{
					reference--;
				}
				else
				{
					reference = list.Count - 1;
				}
			}
			else if (reference < list.Count - 1)
			{
				reference++;
			}
			else
			{
				reference = 0;
			}
			string text = list[reference];
			ChatMessageRef.Invoke(chat) = text;
			((TMP_Text)chat.chatText).text = text;
			((SemiUI)ChatUI.instance).SemiUITextFlashColor(Color.cyan, 0.2f);
			((SemiUI)ChatUI.instance).SemiUISpringShakeY(2f, 5f, 0.2f);
			MenuManager.instance.MenuEffectClick((MenuClickEffectType)4, (MenuPage)null, 1f, 0.2f, true);
		}

		private void SendOrClose()
		{
			ChatManager instance = ChatManager.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if ((ChatMessageRef.Invoke(instance) ?? "") != "")
				{
					instance.ForceConfirmChat();
					return;
				}
				StateSet(instance, (ChatState)0);
				Open = false;
			}
		}

		private void Cancel()
		{
			ChatManager instance = ChatManager.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				StateSet(instance, (ChatState)0);
				((SemiUI)ChatUI.instance).SemiUISpringShakeX(10f, 10f, 0.3f);
				((SemiUI)ChatUI.instance).SemiUISpringScale(0.05f, 5f, 0.2f);
				MenuManager.instance.MenuEffectClick((MenuClickEffectType)2, (MenuPage)null, 1f, 1f, true);
				Open = false;
			}
		}

		private static void WarnOnce(Exception e)
		{
			if (!_warned)
			{
				_warned = true;
				Plugin.Log.LogWarning((object)("[ChatKeyboard] Error (further warnings suppressed): " + e.Message));
			}
		}

		private void OnGUI()
		{
			if (Open)
			{
				float value = Plugin.ChatScale.Value;
				_core.Draw(value, Mathf.Max(40f * value, (float)Screen.height * 0.13f));
				PanelTop = _core.LastPanelTop;
			}
		}
	}
	[HarmonyPatch]
	internal static class ChatKeyboardMapGuard
	{
		[HarmonyPatch(typeof(InputManager), "KeyDown")]
		[HarmonyPostfix]
		private static void KeyDownPostfix(InputKey key, ref bool __result)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if (__result && (int)key == 8 && ChatKeyboard.Open)
			{
				__result = false;
			}
		}

		[HarmonyPatch(typeof(InputManager), "KeyHold")]
		[HarmonyPostfix]
		private static void KeyHoldPostfix(InputKey key, ref bool __result)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if (__result && (int)key == 8 && ChatKeyboard.Open)
			{
				__result = false;
			}
		}
	}
	internal class ChatLog : MonoBehaviour
	{
		private struct Entry
		{
			public string Name;

			public string Text;
		}

		private const int MaxEntries = 30;

		private const float FadeSeconds = 1f;

		private static readonly List<Entry> Entries = new List<Entry>();

		private static float _lastMessageTime = -1000f;

		private static int _entriesVersion;

		private GUIStyle _line;

		private GUIStyle _name;

		private float _styleScale = -1f;

		private int _layoutVersion = -1;

		private int _layoutCount;

		private float _layoutScale = -1f;

		private float _panelW;

		private float _layoutScreenW = -1f;

		private float[] _nameWidths;

		internal static void Append(string name, string text)
		{
			Entries.Add(new Entry
			{
				Name = (string.IsNullOrEmpty(name) ? "???" : name) + ":",
				Text = " " + text
			});
			if (Entries.Count > 30)
			{
				Entries.RemoveAt(0);
			}
			_lastMessageTime = Time.unscaledTime;
			_entriesVersion++;
		}

		private void OnGUI()
		{
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Expected O, but got Unknown
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled.Value || !Plugin.ChatLogEnabled.Value || Entries.Count == 0)
			{
				return;
			}
			float num = VisibleAlpha();
			if (num <= 0f)
			{
				return;
			}
			float num2 = Plugin.ChatScale.Value * 2.142857f;
			EnsureStyles(num2);
			int num3 = Mathf.Min(Plugin.ChatLogMaxVisible.Value, Entries.Count);
			float num4 = 20f * num2;
			float num5 = 8f * num2;
			float num6 = 5f * num2;
			float num7 = 12f * num2;
			if (_layoutVersion != _entriesVersion || !Mathf.Approximately(_layoutScale, num2) || _layoutCount != num3 || !Mathf.Approximately(_layoutScreenW, (float)Screen.width))
			{
				_layoutVersion = _entriesVersion;
				_layoutScale = num2;
				_layoutCount = num3;
				_layoutScreenW = Screen.width;
				if (_nameWidths == null || _nameWidths.Length < num3)
				{
					_nameWidths = new float[num3];
				}
				_panelW = 0f;
				for (int i = 0; i < num3; i++)
				{
					Entry entry = Entries[Entries.Count - num3 + i];
					float x = _name.CalcSize(new GUIContent(entry.Name)).x;
					float x2 = _line.CalcSize(new GUIContent(entry.Text)).x;
					_nameWidths[i] = x;
					_panelW = Mathf.Max(_panelW, x + x2);
				}
				_panelW = Mathf.Min(_panelW + 2f * num5, (float)Screen.width - 2f * num7);
			}
			float num8 = (float)num3 * num4 + 2f * num6;
			float num9 = (float)Screen.height - num7;
			if (ChatKeyboard.Open && ChatKeyboard.PanelTop > 0f)
			{
				num9 = ChatKeyboard.PanelTop - num7;
			}
			float num10 = num7;
			float num11 = num9 - num8;
			GUI.color = new Color(0f, 0f, 0f, 0.55f * num);
			GUI.DrawTexture(new Rect(num10, num11, _panelW, num8), (Texture)(object)Texture2D.whiteTexture);
			for (int j = 0; j < num3; j++)
			{
				Entry entry2 = Entries[Entries.Count - num3 + j];
				float num12 = num11 + num6 + (float)j * num4;
				GUI.color = new Color(1f, 0.85f, 0.3f, num);
				GUI.Label(new Rect(num10 + num5, num12, _nameWidths[j], num4), entry2.Name, _name);
				GUI.color = new Color(1f, 1f, 1f, num);
				GUI.Label(new Rect(num10 + num5 + _nameWidths[j], num12, Mathf.Max(0f, _panelW - 2f * num5 - _nameWidths[j]), num4), entry2.Text, _line);
			}
			GUI.color = Color.white;
		}

		private static float VisibleAlpha()
		{
			ChatManager instance = ChatManager.instance;
			if ((Object)(object)instance != (Object)null && !instance.StateIsInactive())
			{
				return 1f;
			}
			float value = Plugin.ChatLogVisibleSeconds.Value;
			if (value <= 0f)
			{
				return 0f;
			}
			float num = value - (Time.unscaledTime - _lastMessageTime);
			if (num <= 0f)
			{
				return 0f;
			}
			if (!(num >= 1f))
			{
				return num / 1f;
			}
			return 1f;
		}

		private void EnsureStyles(float scale)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0053: 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_0075: Expected O, but got Unknown
			if (_line == null || !Mathf.Approximately(_styleScale, scale))
			{
				_styleScale = scale;
				_line = new GUIStyle(GUI.skin.label)
				{
					fontSize = (int)(14f * scale),
					alignment = (TextAnchor)3
				};
				_line.normal.textColor = Color.white;
				_name = new GUIStyle(_line)
				{
					fontStyle = (FontStyle)1
				};
				_layoutScale = -1f;
			}
		}
	}
	[HarmonyPatch]
	internal static class ChatLogCapturePatch
	{
		private static readonly FieldRef<PlayerAvatar, string> PlayerNameRef;

		private static bool _warned;

		static ChatLogCapturePatch()
		{
			try
			{
				PlayerNameRef = AccessTools.FieldRefAccess<PlayerAvatar, string>("playerName");
			}
			catch
			{
				PlayerNameRef = null;
			}
		}

		[HarmonyPatch(typeof(PlayerAvatar), "ChatMessageSpeak")]
		[HarmonyPostfix]
		private static void Postfix(PlayerAvatar __instance, string _message)
		{
			if (!Plugin.Enabled.Value || !Plugin.ChatLogEnabled.Value)
			{
				return;
			}
			try
			{
				if (PlayerNameRef == null)
				{
					WarnOnce("playerName field not found");
				}
				else
				{
					ChatLog.Append(PlayerNameRef.Invoke(__instance), _message);
				}
			}
			catch (Exception ex)
			{
				WarnOnce(ex.Message);
			}
		}

		private static void WarnOnce(string why)
		{
			if (!_warned)
			{
				_warned = true;
				Plugin.Log.LogWarning((object)("[ChatLog] Capture disabled (further warnings suppressed): " + why));
			}
		}
	}
	internal static class ControllerDetect
	{
		internal enum Kind
		{
			None,
			Xbox,
			PlayStation,
			Switch,
			Generic
		}

		internal enum Style
		{
			Auto,
			Xbox,
			PlayStation,
			Switch
		}

		private static Kind _detected;

		private static bool _padActiveInit;

		internal static Kind Current => ((Plugin.GlyphStyle != null) ? Plugin.GlyphStyle.Value : Style.Auto) switch
		{
			Style.Xbox => Kind.Xbox, 
			Style.PlayStation => Kind.PlayStation, 
			Style.Switch => Kind.Switch, 
			_ => _detected, 
		};

		internal static bool PadActive { get; private set; }

		internal static bool PadTouchedThisLevel { get; private set; }

		internal static void ResetLevelTouch()
		{
			PadTouchedThisLevel = false;
		}

		internal static void TrackActiveInput()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_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_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			Gamepad current = Gamepad.current;
			if (current == null)
			{
				PadActive = false;
				_padActiveInit = true;
				return;
			}
			if (!_padActiveInit)
			{
				_padActiveInit = true;
				PadActive = true;
			}
			Vector2 val = ((InputControl<Vector2>)(object)current.leftStick).ReadValue();
			if (!(((Vector2)(ref val)).sqrMagnitude > 0.02f))
			{
				val = ((InputControl<Vector2>)(object)current.rightStick).ReadValue();
				if (!(((Vector2)(ref val)).sqrMagnitude > 0.02f) && !(((InputControl<Vector2>)(object)current.dpad).ReadValue() != Vector2.zero) && !current.buttonSouth.isPressed && !current.buttonEast.isPressed && !current.buttonWest.isPressed && !current.buttonNorth.isPressed && !current.leftTrigger.isPressed && !current.rightTrigger.isPressed && !current.leftShoulder.isPressed && !current.rightShoulder.isPressed && !current.startButton.isPressed && !current.selectButton.isPressed && !current.leftStickButton.isPressed && !current.rightStickButton.isPressed)
				{
					Mouse current2 = Mouse.current;
					int num;
					if (current2 != null)
					{
						val = ((InputControl<Vector2>)(object)((Pointer)current2).delta).ReadValue();
						num = ((((Vector2)(ref val)).sqrMagnitude > 4f || current2.leftButton.isPressed || current2.rightButton.isPressed) ? 1 : 0);
					}
					else
					{
						num = 0;
					}
					Keyboard current3 = Keyboard.current;
					bool flag = current3 != null && ((ButtonControl)current3.anyKey).isPressed;
					if (((uint)num | (flag ? 1u : 0u)) != 0)
					{
						PadActive = false;
					}
					return;
				}
			}
			PadActive = true;
			PadTouchedThisLevel = true;
		}

		internal static void Init()
		{
			Detect();
			InputSystem.onDeviceChange += delegate(InputDevice device, InputDeviceChange change)
			{
				if (device is Gamepad)
				{
					Detect();
				}
			};
		}

		private static void Detect()
		{
			Gamepad current = Gamepad.current;
			Kind kind = Classify(current);
			if (kind != _detected)
			{
				_detected = kind;
				string arg = ((current == null) ? "none" : (((InputControl)current).displayName + " (layout=" + ((InputControl)current).layout + ")"));
				Style style = ((Plugin.GlyphStyle != null) ? Plugin.GlyphStyle.Value : Style.Auto);
				string arg2 = ((style == Style.Auto) ? "" : $" (glyph override active: {style})");
				Plugin.Log.LogInfo((object)$"[Gamepad] Detected controller: {kind} — {arg}{arg2}");
			}
		}

		private static Kind Classify(Gamepad gp)
		{
			//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)
			if (gp == null)
			{
				return Kind.None;
			}
			InputDeviceDescription description = ((InputDevice)gp).description;
			string text = (((InputDeviceDescription)(ref description)).manufacturer + " " + ((InputDeviceDescription)(ref description)).product + " " + ((InputControl)gp).layout + " " + ((InputControl)gp).name).ToLowerInvariant();
			if (text.Contains("dualsense") || text.Contains("dualshock") || text.Contains("sony") || text.Contains("playstation") || text.Contains("wireless controller"))
			{
				return Kind.PlayStation;
			}
			if (text.Contains("switch") || text.Contains("pro controller") || text.Contains("nintendo") || text.Contains("joy-con"))
			{
				return Kind.Switch;
			}
			if (text.Contains("xinput") || text.Contains("xbox"))
			{
				return Kind.Xbox;
			}
			return Kind.Generic;
		}
	}
	internal static class ControllerGlyphs
	{
		private static Font _symbol;

		private static bool _tried;

		private static GUIStyle _shapeStyle;

		private static Font Symbol()
		{
			if (!_tried)
			{
				_tried = true;
				try
				{
					_symbol = Font.CreateDynamicFontFromOSFont(new string[4] { "Arial Unicode MS", "Segoe UI Symbol", "Segoe UI", "Arial" }, 16);
				}
				catch
				{
					_symbol = null;
				}
			}
			return _symbol;
		}

		private static bool IsSymbol(char c)
		{
			if (c != '○' && c != '□' && c != '△' && c != '←' && c != '↑' && c != '→')
			{
				return c == '↓';
			}
			return true;
		}

		private static bool HasSymbol(string s)
		{
			for (int i = 0; i < s.Length; i++)
			{
				if (IsSymbol(s[i]))
				{
					return true;
				}
			}
			return false;
		}

		internal static void DrawLabel(Rect rect, string text, GUIStyle style)
		{
			//IL_0017: 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_0077: 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_0031: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_00ba: 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)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			Font val = Symbol();
			if ((Object)(object)val == (Object)null || !HasSymbol(text))
			{
				GUI.Label(rect, text, style);
				return;
			}
			if (_shapeStyle == null)
			{
				_shapeStyle = new GUIStyle();
			}
			_shapeStyle.font = val;
			_shapeStyle.fontSize = style.fontSize;
			_shapeStyle.fontStyle = style.fontStyle;
			_shapeStyle.alignment = (TextAnchor)0;
			_shapeStyle.normal.textColor = style.normal.textColor;
			float num = ((Rect)(ref rect)).x;
			int i = 0;
			while (i < text.Length)
			{
				if (IsSymbol(text[i]))
				{
					string text2 = text[i].ToString();
					float x = _shapeStyle.CalcSize(new GUIContent(text2)).x;
					GUI.Label(new Rect(num, ((Rect)(ref rect)).y, x, ((Rect)(ref rect)).height), text2, _shapeStyle);
					num += x;
					i++;
					continue;
				}
				int num2 = i;
				for (; i < text.Length && !IsSymbol(text[i]); i++)
				{
				}
				string text3 = text.Substring(num2, i - num2);
				float x2 = style.CalcSize(new GUIContent(text3)).x;
				GUI.Label(new Rect(num, ((Rect)(ref rect)).y, x2, ((Rect)(ref rect)).height), text3, style);
				num += x2;
			}
		}
	}
	internal class ControllerLayoutOverlay : MonoBehaviour
	{
		private static readonly FieldRef<MenuManager, int> StateRef = AccessTools.FieldRefAccess<MenuManager, int>("currentMenuState");

		internal static bool Visible;

		private static int _openFrame;

		private GUIStyle _title;

		private GUIStyle _row;

		private GUIStyle _key;

		internal static void Toggle()
		{
			Visible = !Visible;
			if (Visible)
			{
				_openFrame = Time.frameCount;
			}
		}

		private static bool MenuOpen()
		{
			MenuManager instance = MenuManager.instance;
			if ((Object)(object)instance != (Object)null)
			{
				return StateRef.Invoke(instance) == 0;
			}
			return false;
		}

		private void Update()
		{
			if (!Plugin.Enabled.Value)
			{
				Visible = false;
				return;
			}
			Gamepad current = Gamepad.current;
			if (current == null)
			{
				Visible = false;
				return;
			}
			if (Visible && Time.frameCount > _openFrame + 1 && (AnyButtonPressed(current) || MouseClicked()))
			{
				Visible = false;
			}
			if (!MenuOpen())
			{
				Visible = false;
			}
		}

		private static bool MouseClicked()
		{
			Mouse current = Mouse.current;
			if (current != null)
			{
				if (!current.leftButton.wasPressedThisFrame)
				{
					return current.rightButton.wasPressedThisFrame;
				}
				return true;
			}
			return false;
		}

		private static bool AnyButtonPressed(Gamepad gp)
		{
			if (!gp.buttonSouth.wasPressedThisFrame && !gp.buttonEast.wasPressedThisFrame && !gp.buttonWest.wasPressedThisFrame && !gp.buttonNorth.wasPressedThisFrame && !gp.leftShoulder.wasPressedThisFrame && !gp.rightShoulder.wasPressedThisFrame && !gp.leftTrigger.wasPressedThisFrame && !gp.rightTrigger.wasPressedThisFrame && !gp.dpad.up.wasPressedThisFrame && !gp.dpad.down.wasPressedThisFrame && !gp.dpad.left.wasPressedThisFrame && !gp.dpad.right.wasPressedThisFrame && !gp.startButton.wasPressedThisFrame && !gp.selectButton.wasPressedThisFrame && !gp.leftStickButton.wasPressedThisFrame)
			{
				return gp.rightStickButton.wasPressedThisFrame;
			}
			return true;
		}

		private void OnGUI()
		{
			//IL_002d: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			if (!Visible)
			{
				return;
			}
			EnsureStyles();
			List<KeyValuePair<string, string>> list = Rows(ControllerDetect.Current);
			GUI.color = new Color(0f, 0f, 0f, 0.6f);
			GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture);
			float num = 520f;
			float num2 = 26f;
			float num3 = 60f + (float)list.Count * num2;
			float num4 = ((float)Screen.width - num) / 2f;
			float num5 = ((float)Screen.height - num3) / 2f;
			GUI.color = new Color(0.1f, 0.1f, 0.1f, 0.95f);
			GUI.DrawTexture(new Rect(num4, num5, num, num3), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = Color.white;
			GUI.Label(new Rect(num4, num5 + 12f, num, 30f), "Controller Layout", _title);
			float num6 = num5 + 50f;
			foreach (KeyValuePair<string, string> item in list)
			{
				GUI.Label(new Rect(num4 + 24f, num6, num * 0.55f, num2), item.Key, _row);
				ControllerGlyphs.DrawLabel(new Rect(num4 + num * 0.55f, num6, num * 0.4f, num2), item.Value, _key);
				num6 += num2;
			}
		}

		private static List<KeyValuePair<string, string>> Rows(ControllerDetect.Kind k)
		{
			List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
			list.Add(R("Move / Look", N(ButtonNames.Control.LStick) + " / " + N(ButtonNames.Control.RStick)));
			list.Add(R("Jump", N(ButtonNames.Control.South)));
			list.Add(R("Interact", N(ButtonNames.Control.West)));
			list.Add(R("Tumble", N(ButtonNames.Control.East)));
			list.Add(R("Map", N(ButtonNames.Control.North)));
			list.Add(R("Sprint / Crouch", N(ButtonNames.Control.L3) + " / " + N(ButtonNames.Control.R3)));
			list.Add(R("Grab / Rotate", N(ButtonNames.Control.RT) + " / " + N(ButtonNames.Control.LT)));
			list.Add(R("Push / Pull", N(ButtonNames.Control.RB) + " / " + N(ButtonNames.Control.LB)));
			list.Add(R("Pause / Chat", N(ButtonNames.Control.Start) + " / " + N(ButtonNames.Control.Select)));
			list.Add(R("Inventory 1 / 2 / 3", N(ButtonNames.Control.DpadLeft) + " / " + N(ButtonNames.Control.DpadUp) + " / " + N(ButtonNames.Control.DpadRight)));
			list.Add(R("Emotes", "hold " + N(ButtonNames.Control.DpadDown)));
			list.Add(R("View this layout", "Settings menu"));
			list.Add(R("Menu: Select / Back", N(ButtonNames.Control.South) + " / " + N(ButtonNames.Control.East)));
			return list;
			string N(ButtonNames.Control c)
			{
				return ButtonNames.Of(c, k);
			}
			static KeyValuePair<string, string> R(string a, string b)
			{
				return new KeyValuePair<string, string>(a, b);
			}
		}

		private void EnsureStyles()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0071: 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_008b: 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_009f: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			if (_title == null)
			{
				_title = new GUIStyle(GUI.skin.label)
				{
					fontSize = 22,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4
				};
				_title.normal.textColor = Color.white;
				_row = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16
				};
				_row.normal.textColor = Color.white;
				_key = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16,
					fontStyle = (FontStyle)1
				};
				_key.normal.textColor = new Color(1f, 0.85f, 0.3f);
			}
		}
	}
	internal class EmoteWheel : MonoBehaviour
	{
		private static readonly FieldRef<MenuManager, int> MenuStateRef;

		private static readonly FieldRef<ChatManager, bool> ChatActiveRef;

		private static readonly Action<PlayerExpression, int, float, bool> DoExpression;

		private static readonly FieldRef<DataDirector, bool> ToggleMuteRef;

		internal static bool Open;

		private const int SegmentCount = 7;

		private const int ExpressionCount = 6;

		private const int MuteSegment = 7;

		private const float MinDeflection = 0.35f;

		private static readonly float[] SegmentAngles;

		private static readonly Dictionary<int, float> Active;

		private static readonly List<int> Expired;

		private static string[] _labels;

		private static bool _warned;

		private static bool _muteWarned;

		private int _hovered;

		private static Transform _previewCam;

		private static bool _camMoved;

		private static Vector3 _camHomeLocal;

		private GUIStyle _title;

		private GUIStyle _label;

		private GUIStyle _labelHover;

		private GUIStyle _labelActive;

		private GUIStyle _labelDisabled;

		static EmoteWheel()
		{
			MenuStateRef = AccessTools.FieldRefAccess<MenuManager, int>("currentMenuState");
			ChatActiveRef = AccessTools.FieldRefAccess<ChatManager, bool>("chatActive");
			DoExpression = AccessTools.MethodDelegate<Action<PlayerExpression, int, float, bool>>(AccessTools.Method(typeof(PlayerExpression), "DoExpression", (Type[])null, (Type[])null), (object)null, true);
			SegmentAngles = new float[8] { 0f, 15f, 45f, 75f, 105f, 135f, 165f, 270f };
			Active = new Dictionary<int, float>();
			Expired = new List<int>();
			try
			{
				ToggleMuteRef = AccessTools.FieldRefAccess<DataDirector, bool>("toggleMute");
			}
			catch
			{
				ToggleMuteRef = null;
			}
		}

		internal static void ResetState()
		{
			Active.Clear();
			_labels = null;
			Open = false;
			_previewCam = null;
			_camMoved = false;
		}

		private void Update()
		{
			//IL_0056: 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)
			if (!Plugin.Enabled.Value || !Plugin.EmoteWheelEnabled.Value)
			{
				Close();
				return;
			}
			Gamepad current = Gamepad.current;
			if (current == null || !InGameplay())
			{
				Close();
				return;
			}
			if (current.dpad.down.isPressed)
			{
				Open = true;
				_hovered = HoveredSegment(((InputControl<Vector2>)(object)current.rightStick).ReadValue());
			}
			else if (Open)
			{
				int num = HoveredSegment(((InputControl<Vector2>)(object)current.rightStick).ReadValue());
				if (num == 0)
				{
					num = _hovered;
				}
				Close();
				switch (num)
				{
				case 7:
					ToggleMute();
					break;
				default:
					ToggleExpression(num);
					break;
				case 0:
					break;
				}
			}
			DriveActiveExpressions();
		}

		private void LateUpdate()
		{
			//IL_0059: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_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)
			if (!Open && Active.Count <= 0)
			{
				RestoreCamera();
				return;
			}
			PlayerExpressionsUI instance = PlayerExpressionsUI.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Transform val = FindPreviewCamera(instance);
			if (!((Object)(object)val == (Object)null))
			{
				if (!_camMoved)
				{
					_camHomeLocal = val.localPosition;
					_camMoved = true;
				}
				val.localPosition = _camHomeLocal;
				val.position += val.forward * (0f - Plugin.EmoteZoomOut.Value) + val.up * (0f - Plugin.EmoteCameraLower.Value);
			}
		}

		private static Transform FindPreviewCamera(PlayerExpressionsUI ui)
		{
			if ((Object)(object)_previewCam != (Object)null)
			{
				return _previewCam;
			}
			if ((Object)(object)ui.PlayerAvatarMenu == (Object)null)
			{
				return null;
			}
			PlayerAvatarMenu component = ui.PlayerAvatarMenu.GetComponent<PlayerAvatarMenu>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.cameraAndStuff == (Object)null)
			{
				return null;
			}
			Camera componentInChildren = ((Component)component.cameraAndStuff).GetComponentInChildren<Camera>(true);
			if ((Object)(object)componentInChildren == (Object)null)
			{
				return null;
			}
			_previewCam = ((Component)componentInChildren).transform;
			return _previewCam;
		}

		private static void RestoreCamera()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (_camMoved)
			{
				_camMoved = false;
				if ((Object)(object)_previewCam != (Object)null)
				{
					_previewCam.localPosition = _camHomeLocal;
				}
			}
		}

		private static void DriveActiveExpressions()
		{
			if (Active.Count == 0)
			{
				return;
			}
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerExpression == (Object)null)
			{
				return;
			}
			PlayerExpression val = (((Object)(object)PlayerExpressionsUI.instance != (Object)null) ? PlayerExpressionsUI.instance.playerExpression : null);
			Expired.Clear();
			if (Plugin.EmoteDurationSeconds.Value > 0f)
			{
				foreach (int item in new List<int>(Active.Keys))
				{
					Active[item] -= Time.deltaTime;
					if (Active[item] <= 0f)
					{
						Expired.Add(item);
					}
				}
				foreach (int item2 in Expired)
				{
					Active.Remove(item2);
				}
				if (Active.Count == 0)
				{
					return;
				}
			}
			try
			{
				foreach (int key in Active.Keys)
				{
					DoExpression(instance.playerExpression, key, 100f, arg4: true);
					if ((Object)(object)val != (Object)null)
					{
						val.OverrideExpressionSet(key, 100f);
					}
				}
			}
			catch (Exception ex)
			{
				if (!_warned)
				{
					Plugin.Log.LogWarning((object)("[EmoteWheel] DoExpression failed: " + ex.Message));
					_warned = true;
				}
			}
		}

		private void Close()
		{
			Open = false;
			_hovered = 0;
		}

		private static bool InGameplay()
		{
			MenuManager instance = MenuManager.instance;
			if ((Object)(object)instance != (Object)null && MenuStateRef.Invoke(instance) == 0)
			{
				return false;
			}
			ChatManager instance2 = ChatManager.instance;
			if ((Object)(object)instance2 != (Object)null && ChatActiveRef.Invoke(instance2))
			{
				return false;
			}
			return (Object)(object)PlayerAvatar.instance != (Object)null;
		}

		private int HoveredSegment(Vector2 stick)
		{
			//IL_0021: 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)
			float num = Mathf.Max(Plugin.StickDeadzone.Value, 0.35f);
			if (((Vector2)(ref stick)).magnitude < num)
			{
				return 0;
			}
			float num2 = Mathf.Atan2(stick.x, stick.y) * 57.29578f;
			int result = 0;
			float num3 = float.MaxValue;
			for (int i = 1; i <= 7; i++)
			{
				float num4 = Mathf.Abs(Mathf.DeltaAngle(num2, SegmentAngles[i]));
				if (num4 < num3)
				{
					num3 = num4;
					result = i;
				}
			}
			return result;
		}

		private static void ToggleExpression(int index)
		{
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerExpression == (Object)null)
			{
				return;
			}
			try
			{
				if (Active.Remove(index))
				{
					Plugin.Log.LogDebug((object)$"[EmoteWheel] Expression {index} OFF");
					return;
				}
				Active.Clear();
				DoExpression(instance.playerExpression, index, 100f, arg4: true);
				float value = Plugin.EmoteDurationSeconds.Value;
				Active[index] = ((value > 0f) ? value : float.PositiveInfinity);
				Plugin.Log.LogDebug((object)$"[EmoteWheel] Expression {index} ON");
			}
			catch (Exception ex)
			{
				if (!_warned)
				{
					Plugin.Log.LogWarning((object)("[EmoteWheel] Expression call failed: " + ex.Message));
					_warned = true;
				}
			}
		}

		private static void ToggleMute()
		{
			if (!SemiFunc.IsMultiplayer())
			{
				return;
			}
			DataDirector instance = DataDirector.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (ToggleMuteRef == null)
			{
				if (!_muteWarned)
				{
					Plugin.Log.LogWarning((object)"[EmoteWheel] DataDirector.toggleMute not found -- mute slot disabled.");
					_muteWarned = true;
				}
				return;
			}
			try
			{
				ref bool reference = ref ToggleMuteRef.Invoke(instance);
				reference = !reference;
				Plugin.Log.LogDebug((object)("[EmoteWheel] Mic mute " + (reference ? "ON" : "OFF")));
			}
			catch (Exception ex)
			{
				if (!_muteWarned)
				{
					Plugin.Log.LogWarning((object)("[EmoteWheel] Mute toggle failed: " + ex.Message));
					_muteWarned = true;
				}
			}
		}

		private static bool IsMuted()
		{
			DataDirector instance = DataDirector.instance;
			if ((Object)(object)instance == (Object)null || ToggleMuteRef == null)
			{
				return false;
			}
			try
			{
				return ToggleMuteRef.Invoke(instance);
			}
			catch
			{
				return false;
			}
		}

		private void OnGUI()
		{
			//IL_0047: 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_0076: 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_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			if (!Open)
			{
				return;
			}
			EnsureStyles();
			EnsureLabels();
			float num = (float)Screen.width / 2f;
			float num2 = (float)Screen.height / 2f;
			float num3 = 190f;
			GUI.color = new Color(0f, 0f, 0f, 0.35f);
			GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = Color.white;
			GUI.Label(new Rect(num - 200f, num2 - num3 - 70f, 400f, 30f), "Emotes", _title);
			Rect val = default(Rect);
			for (int i = 1; i <= 7; i++)
			{
				float num4 = SegmentAngles[i] * (MathF.PI / 180f);
				float num5 = num + Mathf.Sin(num4) * num3;
				float num6 = num2 - Mathf.Cos(num4) * num3;
				((Rect)(ref val))..ctor(num5 - 80f, num6 - 20f, 160f, 40f);
				bool flag = i != 7 || SemiFunc.IsMultiplayer();
				GUI.color = ((i == _hovered && flag) ? new Color(0.3f, 0.26f, 0.08f, 0.95f) : new Color(0.1f, 0.1f, 0.1f, 0.9f));
				GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
				GUI.color = Color.white;
				if (i == 7)
				{
					bool num7 = SemiFunc.IsMultiplayer();
					bool flag2 = num7 && IsMuted();
					string text = ((!num7) ? "Mute (MP only)" : (flag2 ? "Unmute Mic" : "Mute Mic"));
					GUIStyle val2 = ((!num7) ? _labelDisabled : ((i == _hovered) ? _labelHover : (flag2 ? _labelActive : _label)));
					GUI.Label(val, text, val2);
				}
				else
				{
					GUIStyle val3 = ((i == _hovered) ? _labelHover : (Active.ContainsKey(i) ? _labelActive : _label));
					GUI.Label(val, _labels[i], val3);
				}
			}
		}

		private static void EnsureLabels()
		{
			if (_labels != null)
			{
				return;
			}
			_labels = new string[8];
			List<ExpressionSettings> list = null;
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance.playerExpression != (Object)null)
			{
				list = instance.playerExpression.expressions;
			}
			for (int i = 1; i <= 6; i++)
			{
				string text = null;
				if (list != null && i < list.Count && list[i] != null)
				{
					text = list[i].expressionName;
				}
				_labels[i] = (string.IsNullOrEmpty(text) ? $"Expression {i}" : text);
			}
		}

		private void EnsureStyles()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_006d: Expected O, but got Unknown
			//IL_0078: 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_009a: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			if (_title == null)
			{
				_title = new GUIStyle(GUI.skin.label)
				{
					fontSize = 22,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4
				};
				_title.normal.textColor = Color.white;
				_label = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16,
					alignment = (TextAnchor)4
				};
				_label.normal.textColor = Color.white;
				_labelHover = new GUIStyle(_label)
				{
					fontStyle = (FontStyle)1
				};
				_labelHover.normal.textColor = new Color(1f, 0.85f, 0.3f);
				_labelActive = new GUIStyle(_label)
				{
					fontStyle = (FontStyle)1
				};
				_labelActive.normal.textColor = new Color(0.55f, 0.8f, 1f);
				_labelDisabled = new GUIStyle(_label);
				_labelDisabled.normal.textColor = new Color(0.5f, 0.5f, 0.5f);
			}
		}
	}
	internal enum PadButton
	{
		None,
		South,
		East,
		West,
		North,
		LB,
		RB,
		LT,
		RT,
		L3,
		R3,
		DpadLeft,
		DpadUp,
		DpadRight,
		DpadDown,
		Start,
		Select
	}
	[HarmonyPatch]
	internal static class GamepadBindingsPatch
	{
		private static InputManager _injected;

		private static string _pttPath;

		private static string PathOf(PadButton b)
		{
			return b switch
			{
				PadButton.South => "<Gamepad>/buttonSouth", 
				PadButton.East => "<Gamepad>/buttonEast", 
				PadButton.West => "<Gamepad>/buttonWest", 
				PadButton.North => "<Gamepad>/buttonNorth", 
				PadButton.LB => "<Gamepad>/leftShoulder", 
				PadButton.RB => "<Gamepad>/rightShoulder", 
				PadButton.LT => "<Gamepad>/leftTrigger", 
				PadButton.RT => "<Gamepad>/rightTrigger", 
				PadButton.L3 => "<Gamepad>/leftStickPress", 
				PadButton.R3 => "<Gamepad>/rightStickPress", 
				PadButton.DpadLeft => "<Gamepad>/dpad/left", 
				PadButton.DpadUp => "<Gamepad>/dpad/up", 
				PadButton.DpadRight => "<Gamepad>/dpad/right", 
				PadButton.DpadDown => "<Gamepad>/dpad/down", 
				PadButton.Start => "<Gamepad>/start", 
				PadButton.Select => "<Gamepad>/select", 
				_ => null, 
			};
		}

		[HarmonyPatch(typeof(InputManager), "InitializeInputs")]
		[HarmonyPostfix]
		public static void Postfix(InputManager __instance)
		{
			if (!Plugin.Enabled.Value || _injected == __instance)
			{
				return;
			}
			_injected = __instance;
			try
			{
				Bind(__instance, (InputKey)0, "<Gamepad>/leftStick");
				Bind(__instance, (InputKey)1, "<Gamepad>/buttonSouth");
				Bind(__instance, (InputKey)2, "<Gamepad>/buttonWest");
				Bind(__instance, (InputKey)14, "<Gamepad>/buttonEast");
				Bind(__instance, (InputKey)8, "<Gamepad>/buttonNorth");
				Bind(__instance, (InputKey)15, "<Gamepad>/leftStickPress");
				Bind(__instance, (InputKey)12, "<Gamepad>/rightStickPress");
				Bind(__instance, (InputKey)10, "<Gamepad>/rightTrigger");
				Bind(__instance, (InputKey)11, "<Gamepad>/leftTrigger");
				Bind(__instance, (InputKey)6, "<Gamepad>/start");
				Bind(__instance, (InputKey)7, "<Gamepad>/select");
				Bind(__instance, (InputKey)13, "<Gamepad>/buttonEast");
				Bind(__instance, (InputKey)19, "<Gamepad>/dpad/left");
				Bind(__instance, (InputKey)20, "<Gamepad>/dpad/up");
				Bind(__instance, (InputKey)21, "<Gamepad>/dpad/right");
				if (Plugin.PushToTalkButton.Value != PadButton.None)
				{
					_pttPath = PathOf(Plugin.PushToTalkButton.Value);
					Bind(__instance, (InputKey)25, _pttPath);
				}
				else
				{
					_pttPath = null;
				}
				Plugin.Log.LogInfo((object)"[Gamepad] Bindings injected.");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[Gamepad] Binding injection failed: {arg}");
			}
		}

		[HarmonyPatch(typeof(InputManager), "LoadKeyBindings")]
		[HarmonyPostfix]
		public static void LoadKeyBindingsPostfix()
		{
			if (Plugin.Enabled.Value)
			{
				RebindPushToTalk();
			}
		}

		[HarmonyPatch(typeof(InputManager), "ResetKeyToDefault")]
		[HarmonyPostfix]
		public static void ResetKeyToDefaultPostfix(InputKey key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			if ((int)key == 25 && Plugin.Enabled.Value)
			{
				RebindPushToTalk();
			}
		}

		internal static void RebindPushToTalk()
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_injected == (Object)null)
			{
				return;
			}
			try
			{
				InputAction action = _injected.GetAction((InputKey)25);
				if (action == null)
				{
					return;
				}
				bool enabled = action.enabled;
				if (enabled)
				{
					action.Disable();
				}
				try
				{
					if (_pttPath != null)
					{
						for (int i = 0; i < action.bindings.Count; i++)
						{
							InputBinding val = action.bindings[i];
							if (((InputBinding)(ref val)).path == _pttPath)
							{
								BindingSyntax val2 = InputActionSetupExtensions.ChangeBinding(action, i);
								((BindingSyntax)(ref val2)).Erase();
								break;
							}
						}
						_pttPath = null;
					}
					PadButton value = Plugin.PushToTalkButton.Value;
					if (value != PadButton.None)
					{
						_pttPath = PathOf(value);
						InputActionSetupExtensions.AddBinding(action, _pttPath, (string)null, (string)null, (string)null);
					}
				}
				finally
				{
					if (enabled)
					{
						action.Enable();
					}
				}
				Plugin.Log.LogInfo((object)$"[Gamepad] PushToTalk binding -> {Plugin.PushToTalkButton.Value}.");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[Gamepad] PushToTalk rebind failed: {arg}");
			}
		}

		internal static void Bind(InputManager im, InputKey key, string path, string processors = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0058: 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)
			InputAction action = im.GetAction(key);
			if (action == null)
			{
				Plugin.Log.LogWarning((object)$"[Gamepad] No action for {key}");
				return;
			}
			bool enabled = action.enabled;
			if (enabled)
			{
				action.Disable();
			}
			if (string.IsNullOrEmpty(processors))
			{
				InputActionSetupExtensions.AddBinding(action, path, (string)null, (string)null, (string)null);
			}
			else
			{
				BindingSyntax val = InputActionSetupExtensions.AddBinding(action, path, (string)null, (string)null, (string)null);
				((BindingSyntax)(ref val)).WithProcessors(processors);
			}
			if (enabled)
			{
				action.Enable();
			}
		}
	}
	internal class GrabPromptOverlay : MonoBehaviour
	{
		private struct Prompt
		{
			public string Rich;

			public string Plain;
		}

		private struct SlotLabel
		{
			public TextMeshProUGUI Text;

			public string Original;

			public int SpotIndex;
		}

		private static readonly FieldRef<MenuManager, int> MenuStateRef = AccessTools.FieldRefAccess<MenuManager, int>("currentMenuState");

		private static FieldRef<Aim, State> _aimStateRef;

		private static bool _aimRefFailed;

		private ControllerDetect.Kind _cachedKind = (ControllerDetect.Kind)(-1);

		private Prompt _grab;

		private Prompt _letGo;

		private Prompt _rotate;

		private Prompt _climb;

		private Prompt _rightLine;

		private Prompt _leftLine;

		private GUIStyle _style;

		private bool _showArrows;

		private bool _labelsSwapped;

		private InventorySpot[] _spots;

		private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4];

		private readonly List<SlotLabel> _slotLabels = new List<SlotLabel>(8);

		private void Update()
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected I4, but got Unknown
			ControllerDetect.TrackActiveInput();
			InputDisplayPatch.TickCacheInvalidation();
			_rightLine = default(Prompt);
			_leftLine = default(Prompt);
			_showArrows = false;
			if (!Plugin.Enabled.Value || !Plugin.PromptsEnabled.Value || Gamepad.current == null || !ControllerDetect.PadActive || EmoteWheel.Open)
			{
				return;
			}
			MenuManager instance = MenuManager.instance;
			if ((Object)(object)instance != (Object)null && MenuStateRef.Invoke(instance) == 0)
			{
				return;
			}
			_showArrows = Plugin.InventoryArrows.Value && ControllerDetect.PadTouchedThisLevel;
			Aim instance2 = Aim.instance;
			if ((Object)(object)instance2 == (Object)null || !EnsureAimRef())
			{
				return;
			}
			EnsureNames();
			State val = _aimStateRef.Invoke(instance2);
			switch (val - 1)
			{
			case 0:
				_rightLine = _grab;
				break;
			case 1:
			case 2:
				if (Plugin.GrabToggle.Value)
				{
					_rightLine = _letGo;
				}
				_leftLine = _rotate;
				break;
			case 4:
				_rightLine = _climb;
				break;
			case 3:
				break;
			}
		}

		private static bool EnsureAimRef()
		{
			if (_aimStateRef != null)
			{
				return true;
			}
			if (_aimRefFailed)
			{
				return false;
			}
			try
			{
				_aimStateRef = AccessTools.FieldRefAccess<Aim, State>("currentState");
				return true;
			}
			catch (Exception ex)
			{
				_aimRefFailed = true;
				Plugin.Log.LogWarning((object)("[Prompts] Aim.currentState unavailable — prompts disabled: " + ex.Message));
				return false;
			}
		}

		private void EnsureNames()
		{
			ControllerDetect.Kind current = ControllerDetect.Current;
			if (current != _cachedKind || _grab.Plain == null)
			{
				_cachedKind = current;
				string button = ButtonNames.Of(ButtonNames.Control.RT, current);
				string button2 = ButtonNames.Of(ButtonNames.Control.LT, current);
				_grab = Make("GRAB", button);
				_letGo = Make("LET GO", button);
				_rotate = Make("ROTATE", button2);
				_climb = Make("CLIMB", button);
			}
		}

		private static Prompt Make(string action, string button)
		{
			return new Prompt
			{
				Rich = "<color=#FFA21C>" + action + "</color> <color=#FFFFFF>[" + button + "]</color>",
				Plain = action + " [" + button + "]"
			};
		}

		private void LateUpdate()
		{
			if (!_showArrows && !_labelsSwapped)
			{
				return;
			}
			if (NeedSlotLabelRefresh())
			{
				_slotLabels.Clear();
				_labelsSwapped = false;
				_spots = Object.FindObjectsOfType<InventorySpot>();
				InventorySpot[] spots = _spots;
				foreach (InventorySpot val in spots)
				{
					int inventorySpotIndex = val.inventorySpotIndex;
					if (inventorySpotIndex < 0 || inventorySpotIndex > 2)
					{
						continue;
					}
					string text = (inventorySpotIndex + 1).ToString();
					TextMeshProUGUI[] componentsInChildren = ((Component)val).GetComponentsInChildren<TextMeshProUGUI>(true);
					foreach (TextMeshProUGUI val2 in componentsInChildren)
					{
						if ((Object)(object)val2 == (Object)(object)val.noItem || ((TMP_Text)val2).text.Trim() == text)
						{
							_slotLabels.Add(new SlotLabel
							{
								Text = val2,
								Original = ((TMP_Text)val2).text,
								SpotIndex = inventorySpotIndex
							});
						}
					}
				}
				if (_slotLabels.Count == 0)
				{
					return;
				}
			}
			ControllerDetect.Kind current = ControllerDetect.Current;
			foreach (SlotLabel slotLabel in _slotLabels)
			{
				if ((Object)(object)slotLabel.Text == (Object)null)
				{
					continue;
				}
				if (_showArrows)
				{
					string text2 = ((slotLabel.SpotIndex == 0) ? ButtonNames.Of(ButtonNames.Control.DpadLeft, current) : ((slotLabel.SpotIndex == 1) ? ButtonNames.Of(ButtonNames.Control.DpadUp, current) : ButtonNames.Of(ButtonNames.Control.DpadRight, current)));
					if (((TMP_Text)slotLabel.Text).text != text2)
					{
						((TMP_Text)slotLabel.Text).text = text2;
					}
				}
				else if (((TMP_Text)slotLabel.Text).text != slotLabel.Original)
				{
					((TMP_Text)slotLabel.Text).text = slotLabel.Original;
				}
			}
			_labelsSwapped = _showArrows;
		}

		private bool NeedSlotLabelRefresh()
		{
			if (_spots == null || _spots.Length == 0 || (Object)(object)_spots[0] == (Object)null || _slotLabels.Count == 0)
			{
				return true;
			}
			foreach (SlotLabel slotLabel in _slotLabels)
			{
				if ((Object)(object)slotLabel.Text == (Object)null)
				{
					return true;
				}
			}
			return false;
		}

		private void OnGUI()
		{
			if (_rightLine.Plain == null && _leftLine.Plain == null)
			{
				return;
			}
			EnsureStyles();
			if (TryInventoryScreenBounds(out var minX, out var maxX, out var centerY))
			{
				float guiCenterY = (float)Screen.height - centerY;
				if (_rightLine.Plain != null)
				{
					DrawChip(_rightLine, maxX + 14f, guiCenterY, rightSide: true);
				}
				if (_leftLine.Plain != null)
				{
					DrawChip(_leftLine, minX - 14f, guiCenterY, rightSide: false);
				}
				return;
			}
			float cx = (float)Screen.width / 2f;
			float num = (float)Screen.height / 2f + 35f;
			if (_rightLine.Plain != null)
			{
				DrawChipCentered(_rightLine, cx, num);
				num += 28f;
			}
			if (_leftLine.Plain != null)
			{
				DrawChipCentered(_leftLine, cx, num);
			}
		}

		private void DrawChip(Prompt p, float anchorX, float guiCenterY, bool rightSide)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0011: 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_0052: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			float num = _style.CalcSize(new GUIContent(p.Plain)).x + 18f;
			Rect val = new Rect(rightSide ? anchorX : (anchorX - num), guiCenterY - 12f, num, 24f);
			GUI.color = new Color(0.08f, 0.08f, 0.08f, 0.85f);
			GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = Color.white;
			GUI.Label(val, p.Rich, _style);
		}

		private void DrawChipCentered(Prompt p, float cx, float y)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0011: 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_004b: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			float num = _style.CalcSize(new GUIContent(p.Plain)).x + 18f;
			Rect val = new Rect(cx - num / 2f, y, num, 24f);
			GUI.color = new Color(0.08f, 0.08f, 0.08f, 0.85f);
			GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = Color.white;
			GUI.Label(val, p.Rich, _style);
		}

		private bool TryInventoryScreenBounds(out float minX, out float maxX, out float centerY)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			minX = float.MaxValue;
			maxX = float.MinValue;
			centerY = 0f;
			CameraOverlay instance = CameraOverlay.instance;
			RenderTextureMain instance2 = RenderTextureMain.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || (Object)(object)instance2.overlayRawImage == (Object)null)
			{
				return false;
			}
			Camera component = ((Component)instance).GetComponent<Camera>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			if (_spots == null || _spots.Length == 0 || (Object)(object)_spots[0] == (Object)null)
			{
				_spots = Object.FindObjectsOfType<InventorySpot>();
				if (_spots.Length == 0)
				{
					return false;
				}
			}
			((Graphic)instance2.overlayRawImage).rectTransform.GetWorldCorners(_corners);
			Vector2 val = Vector2.op_Implicit(_corners[0]);
			Vector2 val2 = Vector2.op_Implicit(_corners[2]);
			float num = 0f;
			int num2 = 0;
			InventorySpot[] spots = _spots;
			foreach (InventorySpot val3 in spots)
			{
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				Transform transform = ((Component)val3).transform;
				RectTransform val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if ((Object)(object)val4 == (Object)null)
				{
					continue;
				}
				val4.GetWorldCorners(_corners);
				for (int j = 0; j < 4; j++)
				{
					Vector3 val5 = component.WorldToViewportPoint(_corners[j]);
					float num3 = Mathf.Lerp(val.x, val2.x, val5.x);
					float num4 = Mathf.Lerp(val.y, val2.y, val5.y);
					if (num3 < minX)
					{
						minX = num3;
					}
					if (num3 > maxX)
					{
						maxX = num3;
					}
					num += num4;
				}
				num2++;
			}
			if (num2 == 0)
			{
				return false;
			}
			centerY = num / (float)(num2 * 4);
			return true;
		}

		private void EnsureStyles()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0028: 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_003b: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (_style == null)
			{
				_style = new GUIStyle(GUI.skin.label)
				{
					fontSize = 14,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4,
					richText = true
				};
				_style.normal.textColor = Color.white;
			}
		}
	}
	[HarmonyPatch]
	internal static class InputDisplayPatch
	{
		private static readonly FieldRef<MenuManager, int> MenuStateRef = AccessTools.FieldRefAccess<MenuManager, int>("currentMenuState");

		private static readonly FieldRef<ItemAttributes, string> ItemTagRef = AccessTools.FieldRefAccess<ItemAttributes, string>("itemTag");

		private static bool _lastControllerActive;

		[HarmonyPatch(typeof(InputManager), "InputDisplayGet")]
		[HarmonyPostfix]
		private static void InputDisplayGetPostfix(InputKey _inputKey, KeyType _keyType, MovementDirection _movementDirection, ref string __result)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			//IL_005c: 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)
			if (!Plugin.Enabled.Value || !Plugin.ControllerKeyTags.Value || Gamepad.current == null || !ControllerDetect.PadActive)
			{
				return;
			}
			MenuManager instance = MenuManager.instance;
			if ((Object)(object)instance != (Object)null && MenuStateRef.Invoke(instance) == 0)
			{
				return;
			}
			if ((int)_keyType == 1)
			{
				__result = (((int)_movementDirection == 0) ? "L-STICK" : "");
				return;
			}
			string text = NameFor(_inputKey, ControllerDetect.Current);
			if (text != null)
			{
				__result = text.ToUpper();
			}
		}

		private static string NameFor(InputKey key, ControllerDetect.Kind kind)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected I4, but got Unknown
			switch (key - 1)
			{
			case 0:
				return B(ButtonNames.Control.South, kind);
			case 1:
				return B(ButtonNames.Control.West, kind);
			case 13:
				return B(ButtonNames.Control.East, kind);
			case 7:
				return B(ButtonNames.Control.North, kind);
			case 14:
				return "L3";
			case 11:
				return "R3";
			case 9:
				return B(ButtonNames.Control.RT, kind);
			case 10:
				return B(ButtonNames.Control.LT, kind);
			case 5:
				return B(ButtonNames.Control.Start, kind);
			case 6:
				return B(ButtonNames.Control.Select, kind);
			case 18:
				return B(ButtonNames.Control.DpadLeft, kind);
			case 19:
				return B(ButtonNames.Control.DpadUp, kind);
			case 20:
				return B(ButtonNames.Control.DpadRight, kind);
			case 3:
				return B(ButtonNames.Control.RB, kind);
			case 4:
				return B(ButtonNames.Control.LB, kind);
			case 25:
			case 26:
			case 27:
			case 28:
			case 29:
			case 30:
				return B(ButtonNames.Control.DpadDown, kind) + " (wheel)";
			default:
				return null;
			}
		}

		private static string B(ButtonNames.Control c, ControllerDetect.Kind kind)
		{
			return ButtonNames.Of(c, kind);
		}

		internal static void TickCacheInvalidation()
		{
			if (!Plugin.Enabled.Value || !Plugin.ControllerKeyTags.Value)
			{
				return;
			}
			bool flag = ControllerDetect.PadActive && Gamepad.current != null;
			if (flag == _lastControllerActive)
			{
				return;
			}
			_lastControllerActive = flag;
			try
			{
				ItemAttributes[] array = Object.FindObjectsOfType<ItemAttributes>();
				foreach (ItemAttributes val in array)
				{
					ItemTagRef.Invoke(val) = "";
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("[Prompts] item tag cache clear failed: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(InputManager))]
	internal static class LookPatch
	{
		private const float AimSpeedFloor = 0.0001f;

		[HarmonyPatch("GetMouseX")]
		[HarmonyPostfix]
		public static void GetMouseXPostfix(ref float __result)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_009f: 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)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled.Value || EmoteWheel.Open || ChatKeyboard.Open)
			{
				return;
			}
			Gamepad current = Gamepad.current;
			if (current != null)
			{
				float num = Deadzone(((InputControl<Vector2>)(object)current.rightStick).ReadValue().x);
				if (Plugin.InvertX.Value)
				{
					num = 0f - num;
				}
				__result += num * Plugin.LookSpeedX.Value;
			}
			if (!Plugin.AimAssistEnabled.Value || !AimAssist.HasTarget)
			{
				return;
			}
			CameraAim instance = CameraAim.Instance;
			Camera main = Camera.main;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)main == (Object)null))
			{
				Vector3 forward = ((Component)main).transform.forward;
				Vector3 val = AimAssist.TargetPosition - ((Component)main).transform.position;
				Vector3 val2 = Vector3.ProjectOnPlane(forward, Vector3.up);
				Vector3 val3 = Vector3.ProjectOnPlane(val, Vector3.up);
				if (!(((Vector3)(ref val2)).sqrMagnitude < 0.0001f) && !(((Vector3)(ref val3)).sqrMagnitude < 0.0001f))
				{
					float axisErrDeg = Vector3.SignedAngle(val2, val3, Vector3.up);
					float totalErrDeg = Vector3.Angle(forward, val);
					__result += Correction(axisErrDeg, totalErrDeg, __result, instance.AimSpeedMouse);
				}
			}
		}

		[HarmonyPatch("GetMouseY")]
		[HarmonyPostfix]
		public static void GetMouseYPostfix(ref float __result)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_009f: 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)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled.Value || EmoteWheel.Open || ChatKeyboard.Open)
			{
				return;
			}
			Gamepad current = Gamepad.current;
			if (current != null)
			{
				float num = Deadzone(((InputControl<Vector2>)(object)current.rightStick).ReadValue().y);
				if (Plugin.InvertY.Value)
				{
					num = 0f - num;
				}
				__result += num * Plugin.LookSpeedY.Value;
			}
			if (Plugin.AimAssistEnabled.Value && AimAssist.HasTarget)
			{
				CameraAim instance = CameraAim.Instance;
				Camera main = Camera.main;
				if (!((Object)(object)instance == (Object)null) && !((Object)(object)main == (Object)null))
				{
					Vector3 forward = ((Component)main).transform.forward;
					Vector3 val = AimAssist.TargetPosition - ((Component)main).transform.position;
					float num2 = Mathf.Asin(Mathf.Clamp(((Vector3)(ref val)).normalized.y, -1f, 1f)) * 57.29578f;
					float num3 = Mathf.Asin(Mathf.Clamp(((Vector3)(ref forward)).normalized.y, -1f, 1f)) * 57.29578f;
					float axisErrDeg = num2 - num3;
					float totalErrDeg = Vector3.Angle(forward, val);
					__result += Correction(axisErrDeg, totalErrDeg, __result, instance.AimSpeedMouse);
				}
			}
		}

		private static float Correction(float axisErrDeg, float totalErrDeg, float playerResult, float aimSpeed)
		{
			aimSpeed = Mathf.Max(0.0001f, aimSpeed);
			float value = Plugin.AimAssistDeadZone.Value;
			float value2 = Plugin.AimAssistMaxAngle.Value;
			float num = ((totalErrDeg <= value) ? 0f : ((!(totalErrDeg >= value2)) ? Mathf.SmoothStep(0f, 1f, (totalErrDeg - value) / Mathf.Max(0.001f, value2 - value)) : 1f));
			if (num <= 0f)
			{
				return 0f;
			}
			float num2 = Plugin.AimAssistGain.Value * axisErrDeg * num;
			float num3 = Mathf.Abs(playerResult) * aimSpeed;
			float num4 = ((!(num3 > Plugin.AimAssistActiveThreshold.Value)) ? Mathf.Min(Plugin.AimAssistIdleDrift.Value * num, Plugin.AimAssistMaxDegPerFrame.Value) : Mathf.Min(Plugin.AimAssistMaxFraction.Value * num3, Plugin.AimAssistMaxDegPerFrame.Value));
			return Mathf.Clamp(num2, 0f - num4, num4) / aimSpeed;
		}

		private static float Deadzone(float v)
		{
			float value = Plugin.StickDeadzone.Value;
			if (!(Mathf.Abs(v) < value))
			{
				return v;
			}
			return 0f;
		}
	}
	[HarmonyPatch(typeof(MenuButton), "ProcessHover")]
	internal static class MenuButtonHoverPatch
	{
		private static readonly FieldRef<MenuButton, bool> HoveringRef = AccessTools.FieldRefAccess<MenuButton, bool>("hovering");

		private static readonly FieldInfo ButtonTextField = AccessTools.Field(typeof(MenuButton), "buttonText");

		private static PropertyInfo s_colorProp;

		[HarmonyPostfix]
		public static void Postfix(MenuButton __instance)
		{
			//IL_0077: 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)
			if (!MenuNavigator.ControllerActive)
			{
				return;
			}
			bool flag = __instance == MenuNavigator.Selected;
			HoveringRef.Invoke(__instance) = flag;
			object obj = ((ButtonTextField != null) ? ButtonTextField.GetValue(__instance) : null);
			if (obj != null)
			{
				if (s_colorProp == null)
				{
					s_colorProp = obj.GetType().GetProperty("color");
				}
				s_colorProp?.SetValue(obj, flag ? __instance.colorHover : __instance.colorNormal);
			}
			if (flag)
			{
				__instance.OnHovering();
			}
		}
	}
	[HarmonyPatch(typeof(MenuCursor), "Show")]
	internal static class MenuCursorHidePatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			if (!Plugin.Enabled.Value || !Plugin.HideMouseCursorOnPad.Value)
			{
				return true;
			}
			return !MenuNavigator.ControllerActive;
		}
	}
	internal class MenuKeyboard : MonoBehaviour
	{
		private static readonly FieldRef<MenuManager, bool> TextInputActiveRef = AccessTools.FieldRefAccess<MenuManager, bool>("textInputActive");

		private static readonly FieldRef<MenuTextInput, string> TextCurrentRef = AccessTools.FieldRefAccess<MenuTextInput, string>("textCurrent");

		private static readonly FieldRef<MenuPagePassword, string> PasswordRef = AccessTools.FieldRefAccess<MenuPagePassword, string>("password");

		internal static bool Open;

		private PadKeyboardCore _core;

		private bool _coreHasSpace;

		private MenuTextInput _textInput;

		private MenuPagePassword _password;

		private bool _dismissed;

		private bool _selectArmed;

		private static bool _warned;

		internal static void ResetState()
		{
			Open = false;
		}

		private void Update()
		{
			MenuManager instance = MenuManager.instance;
			Gamepad current = Gamepad.current;
			if ((Object)(object)instance == (Object)null || current == null || !Plugin.Enabled.Value || !Plugin.MenuKeyboardEnabled.Value)
			{
				Open = false;
				return;
			}
			bool flag;
			try
			{
				flag = TextInputActiveRef.Invoke(instance);
			}
			catch (Exception e)
			{
				WarnOnce(e);
				Open = false;
				return;
			}
			if (!flag)
			{
				Open = false;
				_dismissed = false;
				_textInput = null;
				_password = null;
				return;
			}
			if (!Open && !_dismissed && MenuNavigator.ControllerActive)
			{
				try
				{
					if (AcquireTarget())
					{
						OpenPanel();
					}
				}
				catch (Exception e2)
				{
					WarnOnce(e2);
					return;
				}
			}
			if (!Open)
			{
				return;
			}
			if (!MenuNavigator.ControllerActive)
			{
				Open = false;
				return;
			}
			if (((Object)(object)_password != (Object)null && !((Behaviour)_password).isActiveAndEnabled) || ((Object)(object)_password == (Object)null && ((Object)(object)_textInput == (Object)null || !((Behaviour)_textInput).isActiveAndEnabled)))
			{
				Open = false;
				_textInput = null;
				_password = null;
				return;
			}
			if (!current.selectButton.isPressed && !current.selectButton.wasReleasedThisFrame)
			{
				_selectArmed = true;
			}
			try
			{
				_core.HandleInput(current);
				if (current.buttonEast.wasPressedThisFrame)
				{
					Backspace();
				}
				if (_selectArmed && current.selectButton.wasReleasedThisFrame)
				{
					Dismiss();
				}
			}
			catch (Exception e3)
			{
				WarnOnce(e3);
			}
		}

		private bool AcquireTarget()
		{
			_password = null;
			_textInput = null;
			MenuPagePassword[] array = Object.FindObjectsOfType<MenuPagePassword>();
			foreach (MenuPagePassword val in array)
			{
				if (((Behaviour)val).isActiveAndEnabled)
				{
					_password = val;
					break;
				}
			}
			if ((Object)(object)_password == (Object)null)
			{
				MenuTextInput[] array2 = Object.FindObjectsOfType<MenuTextInput>();
				foreach (MenuTextInput val2 in array2)
				{
					if (((Behaviour)val2).isActiveAndEnabled)
					{
						_textInput = val2;
						break;
					}
				}
			}
			if (!((Object)(object)_password != (Object)null))
			{
				return (Object)(object)_textInput != (Object)null;
			}
			return true;
		}

		private void OpenPanel()
		{
			bool flag = (Object)(object)_password == (Object)null;
			if (_core == null || _coreHasSpace != flag)
			{
				_core = new PadKeyboardCore(flag, "ENTER", "HIDE");
				_core.OnChar = TypeChar;
				_core.OnConfirm = Confirm;
				_core.OnClose = Dismiss;
				_coreHasSpace = flag;
			}
			_core.Reset();
			_selectArmed = false;
			Open = true;
		}

		private void TypeChar(string s)
		{
			if ((Object)(object)_password != (Object)null)
			{
				if (!(s == " "))
				{
					PasswordRef.Invoke(_password) = PasswordRef.Invoke(_password) + s;
				}
			}
			else if ((Object)(object)_textInput != (Object)null)
			{
				string text = TextCurrentRef.Invoke(_textInput) ?? "";
				if (text == "\b")
				{
					text = "";
				}
				TextCurrentRef.Invoke(_textInput) = text + s;
			}
		}

		private void Backspace()
		{
			if ((Object)(object)_password != (Object)null)
			{
				string text = PasswordRef.Invoke(_password) ?? "";
				if (text.Length > 0)
				{
					PasswordRef.Invoke(_password) = text.Remove(text.Length - 1);
				}
			}
			else if ((Object)(object)_textInput != (Object)null)
			{
				string text2 = TextCurrentRef.Invoke(_textInput) ?? "";
				if (!(text2 == "\b") && text2.Length != 0)
				{
					TextCurrentRef.Invoke(_textInput) = text2.Remove(text2.Length - 1);
				}
			}
		}

		private void Confirm()
		{
			if ((Object)(object)_password != (Object)null)
			{
				_password.ConfirmButton();
			}
			else
			{
				if ((Object)(object)_textInput == (Object)null)
				{
					return;
				}
				MenuPageServerListCreateNew val = FindPage<MenuPageServerListCreateNew>();
				if ((Object)(object)val != (Object)null)
				{
					val.ButtonConfirm();
					return;
				}
				MenuPageSavesRename val2 = FindPage<MenuPageSavesRename>();
				if ((Object)(object)val2 != (Object)null)
				{
					val2.ButtonConfirm();
					return;
				}
				MenuPageServerListSearch val3 = FindPage<MenuPageServerListSearch>();
				if ((Object)(object)val3 != (Object)null)
				{
					val3.ButtonConfirm();
				}
				else
				{
					WarnOnce(new Exception("active MenuTextInput has no known confirm owner"));
				}
			}
		}

		private T FindPage<T>() where T : MonoBehaviour
		{
			if ((Object)(object)_textInput == (Object)null)
			{
				return default(T);
			}
			T componentInParent = ((Component)_textInput).GetComponentInParent<T>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return componentInParent;
			}
			T[] array = Object.FindObjectsOfType<T>();
			foreach (T val in array)
			{
				if (((Behaviour)(object)val).isActiveAndEnabled)
				{
					return val;
				}
			}
			return default(T);
		}

		private void Dismiss()
		{
			Open = false;
			_dismissed = true;
		}

		private static void WarnOnce(Exception e)
		{
			if (!_warned)
			{
				_warned = true;
				Plugin.Log.LogWarning((object)("[MenuKeyboard] Error (further warnings suppressed): " + e.Message));
			}
		}

		private void OnGUI()
		{
			if (Open && _core != null)
			{
				_core.Draw(Plugin.ChatScale.Value, 40f * Plugin.ChatScale.Value);
			}
		}
	}
	internal class MenuNavigator : MonoBehaviour
	{
		private struct NavEntry
		{
			public MenuButton Btn;

			public MenuElementHover Hover;

			public Vector2 Pos;

			public Vector2 Min;

			public Vector2 Max;
		}

		private enum PickMode
		{
			Beam,
			Cone,
			Any
		}

		private static readonly FieldRef<MenuManager, int> StateRef = AccessTools.FieldRefAccess<MenuManager, int>("currentMenuState");

		private static readonly FieldRef<MenuManager, List<MenuButton>> ButtonsRef = AccessTools.FieldRefAccess<MenuManager, List<MenuButton>>("allMenuButtons");

		private static readonly FieldRef<MenuManager, MenuPage> CurrentPageRef = AccessTools.FieldRefAccess<MenuManager, MenuPage>("currentMenuPage");

		private static readonly FieldRef<MenuManager, List<MenuPage>> AddedPagesRef = AccessTools.FieldRefAccess<MenuManager, List<MenuPage>>("addedPagesOnTop");

		private static readonly FieldRef<MenuPage, bool> AddedOnTopRef = AccessTools.FieldRefAccess<MenuPage, bool>("addedPageOnTop");

		private static readonly FieldRef<MenuButton, MenuPage> ParentPageRef = AccessTools.FieldRefAccess<MenuButton, MenuPage>("parentPage");

		private static readonly FieldRef<MenuButton, bool> DisabledRef = AccessTools.FieldRefAccess<MenuButton, bool>("disabled");

		private static readonly FieldRef<MenuButton, bool> HoveringRef = AccessTools.FieldRefAccess<MenuButton, bool>("hovering");

		private static readonly FieldRef<MenuPage, PageState> PageStateRef = AccessTools.FieldRefAccess<MenuPage, PageState>("currentPageState");

		private static readonly MethodInfo OnSelectMethod = AccessTools.Method(typeof(MenuButton), "OnSelect", (Type[])null, (Type[])null);

		private static readonly FieldInfo ButtonTextField = AccessTools.Field(typeof(MenuButton), "buttonText");

		private static PropertyInfo s_textProp;

		private static readonly Vector3[] s_corners = (Vector3[])(object)new Vector3[4];

		internal static MenuButton Selected;

		internal static bool ControllerActive;

		internal static RectTransform SelectedHoverRect;

		internal static float SnapSelectionBoxUntil;

		private const float SnapJumpDistance = 150f;

		private static readonly FieldRef<MenuElementSaveFile, string> SaveFileNameRef = AccessTools.FieldRefAccess<MenuElementSaveFile, string>("saveFileName");

		private static readonly FieldRef<MenuElementSaveFile, List<string>> SaveFileBackupsRef = AccessTools.FieldRefAccess<MenuElementSaveFile, List<string>>("saveFileBackups");

		private static readonly FieldRef<SpringFloat, float> SpringVelocityRef = AccessTools.FieldRefAccess<SpringFloat, float>("springVelocity");

		private MenuButton _selected;

		private MenuElementHover _selectedHover;

		private bool _active;

		private float _navCooldown;

		private GUIStyle _style;

		private MenuPage _focusPage;

		private MenuPage _focusOverride;

		private MenuPage _lastTop;

		private readonly Dictionary<MenuPage, MenuButton> _lastByPage = new Dictionary<MenuPage, MenuButton>();

		private static FieldInfo s_repoLastClicked;

		private static bool s_repoLookupDone;

		private bool MenuOpen(out MenuManager mm)
		{
			mm = MenuManager.instance;
			if ((Object)(object)mm != (Object)null)
			{
				return StateRef.Invoke(mm) == 0;
			}
			return false;
		}

		private void Update()
		{
			//IL_00c3: 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)
			ControllerActive = false;
			Selected = null;
			SelectedHoverRect = null;
			if (!Plugin.Enabled.Value)
			{
				return;
			}
			Gamepad current = Gamepad.current;
			if (current == null)
			{
				return;
			}
			if (!MenuOpen(out var mm))
			{
				_selected = null;
				_selectedHover = null;
				_focusOverride = null;
				_focusPage = null;
				_lastTop = null;
				_lastByPage.Clear();
				return;
			}
			ResolveFocus(mm);
			List<MenuButton> list = Candidates(mm, _focusPage);
			List<MenuElementHover> list2 = HoverCandidates(_focusPage);
			if (list.Count == 0 && list2.Count == 0)
			{
				_selected = null;
				_selectedHover = null;
				return;
			}
			if (AnyControllerInput(current))
			{
				_active = true;
			}
			if (Mouse.current != null)
			{
				Vector2 val = ((InputControl<Vector2>)(object)((Pointer)Mouse.current).delta).ReadValue();
				if (((Vector2)(ref val)).sqrMagnitude > 4f)
				{
					_active = false;
				}
			}
			if (_active)
			{
				if (MenuKeyboard.Open)