Decompiled source of Better Proximity Voice v1.4.0

BepInEx/plugins/BigWalk.VoiceSettings.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BigWalk.VoiceSettings")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Best-in-class Big Walk voice controls: adjustable proximity range, 2D audio, named speaker HUD, quick actions, and polished in-game feedback.")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0+48d31be321cabd0bfd7797066d6a8f3764a5f7e9")]
[assembly: AssemblyProduct("BigWalk.VoiceSettings")]
[assembly: AssemblyTitle("BigWalk.VoiceSettings")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BigWalk.VoiceSettings
{
	internal static class NativeSettingsIntegration
	{
		private sealed class AudioScrollState
		{
			private const float EdgePadding = 18f;

			private readonly SettingsMenu _menu;

			private readonly RectTransform _content;

			private readonly RectTransform _viewport;

			private readonly ScrollRect _scrollRect;

			private readonly bool _ownsScrollRect;

			private bool _wasActive;

			private bool _reportedTickError;

			private GameObject _lastSelection;

			public AudioScrollState(SettingsMenu menu, RectTransform content, RectTransform viewport)
			{
				//IL_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_016e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0174: Expected O, but got Unknown
				//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
				_menu = menu;
				_content = content;
				_viewport = viewport;
				ContentSizeFitter val = ((Component)content).GetComponent<ContentSizeFitter>();
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)content).gameObject.AddComponent<ContentSizeFitter>();
				}
				val.horizontalFit = (FitMode)0;
				val.verticalFit = (FitMode)2;
				if ((Object)(object)((Component)viewport).GetComponent<RectMask2D>() == (Object)null && (Object)(object)((Component)viewport).GetComponent<Mask>() == (Object)null)
				{
					((Component)viewport).gameObject.AddComponent<RectMask2D>();
				}
				Image val2 = ((Component)viewport).GetComponent<Image>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = ((Component)viewport).gameObject.AddComponent<Image>();
				}
				((Graphic)val2).color = new Color(0f, 0f, 0f, 0f);
				((Graphic)val2).raycastTarget = true;
				_scrollRect = ((Component)viewport).GetComponent<ScrollRect>();
				if ((Object)(object)_scrollRect == (Object)null)
				{
					_scrollRect = ((Component)viewport).gameObject.AddComponent<ScrollRect>();
					_ownsScrollRect = true;
				}
				_scrollRect.content = content;
				_scrollRect.viewport = viewport;
				_scrollRect.horizontal = false;
				_scrollRect.vertical = true;
				_scrollRect.movementType = (MovementType)2;
				_scrollRect.inertia = true;
				_scrollRect.decelerationRate = 0.135f;
				_scrollRect.scrollSensitivity = 72f;
				LayoutRebuilder.ForceRebuildLayoutImmediate(content);
				Canvas.ForceUpdateCanvases();
				_scrollRect.verticalNormalizedPosition = 1f;
				ManualLogSource trace = Plugin.Trace;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(55, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Audio scrolling enabled: content '");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)((Component)content).gameObject).name);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' ");
					Rect rect = content.rect;
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(((Rect)(ref rect)).height, "0");
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("px, ");
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("viewport '");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)((Component)viewport).gameObject).name);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' ");
					rect = viewport.rect;
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(((Rect)(ref rect)).height, "0");
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("px.");
				}
				trace.LogInfo(val3);
			}

			public void Tick()
			{
				//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d4: Expected O, but got Unknown
				try
				{
					if ((Object)(object)_menu == (Object)null || (Object)(object)_content == (Object)null || (Object)(object)_viewport == (Object)null)
					{
						return;
					}
					bool flag = ((Behaviour)_menu).isActiveAndEnabled && (Object)(object)_menu.activeCatagory == (Object)(object)_menu.catagoryAudio;
					if (_ownsScrollRect)
					{
						((Behaviour)_scrollRect).enabled = flag;
					}
					if (!flag)
					{
						_wasActive = false;
						return;
					}
					if (!_wasActive)
					{
						LayoutRebuilder.ForceRebuildLayoutImmediate(_content);
						Canvas.ForceUpdateCanvases();
						_scrollRect.verticalNormalizedPosition = 1f;
						_wasActive = true;
					}
					KeepSelectionVisible();
				}
				catch (Exception ex)
				{
					if (!_reportedTickError)
					{
						_reportedTickError = true;
						ManualLogSource trace = Plugin.Trace;
						bool flag2 = default(bool);
						BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(64, 1, ref flag2);
						if (flag2)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Audio scrolling update failed (further occurrences suppressed): ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
						}
						trace.LogWarning(val);
					}
				}
			}

			private void KeepSelectionVisible()
			{
				//IL_0074: 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_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a2: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0116: Unknown result type (might be due to invalid IL or missing references)
				//IL_0131: Unknown result type (might be due to invalid IL or missing references)
				//IL_0136: Unknown result type (might be due to invalid IL or missing references)
				//IL_0199: Unknown result type (might be due to invalid IL or missing references)
				//IL_019e: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
				EventSystem current = EventSystem.current;
				GameObject val = ((current != null) ? current.currentSelectedGameObject : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)_lastSelection)
				{
					return;
				}
				Transform val2 = val.transform;
				bool flag = false;
				while ((Object)(object)val2 != (Object)null)
				{
					if ((Object)(object)val2 == (Object)(object)_content)
					{
						flag = true;
						break;
					}
					val2 = val2.parent;
				}
				if (!flag)
				{
					return;
				}
				_lastSelection = val;
				RectTransform component = val.GetComponent<RectTransform>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				float num = Mathf.Abs(((Transform)component).lossyScale.y);
				float num2 = Mathf.Abs(((Transform)_viewport).lossyScale.y);
				Rect rect = component.rect;
				float num3 = ((Rect)(ref rect)).height * num * 0.5f;
				rect = _viewport.rect;
				float num4 = ((Rect)(ref rect)).height * num2 * 0.5f;
				float num5 = ((Transform)component).position.y - num3;
				float num6 = ((Transform)component).position.y + num3;
				float num7 = ((Transform)_viewport).position.y - num4 + 18f;
				float num8 = ((Transform)_viewport).position.y + num4 - 18f;
				Vector2 anchoredPosition = _content.anchoredPosition;
				if (num5 < num7)
				{
					anchoredPosition.y += (num7 - num5) / Mathf.Max(num, 0.001f);
				}
				else
				{
					if (!(num6 > num8))
					{
						return;
					}
					anchoredPosition.y -= (num6 - num8) / Mathf.Max(num, 0.001f);
				}
				float preferredHeight = LayoutUtility.GetPreferredHeight(_content);
				rect = _viewport.rect;
				float num9 = Mathf.Max(0f, preferredHeight - ((Rect)(ref rect)).height);
				anchoredPosition.y = Mathf.Clamp(anchoredPosition.y, 0f, num9);
				_content.anchoredPosition = anchoredPosition;
				_scrollRect.StopMovement();
			}
		}

		private const string RootName = "BigWalk.VoiceSettings.Native.Positioning";

		private const string PositioningName = "BigWalk.VoiceSettings.Native.Positioning";

		private const string RangeName = "BigWalk.VoiceSettings.Native.Range";

		private const string IndicatorsName = "BigWalk.VoiceSettings.Native.Indicators";

		private const string AdvancedName = "BigWalk.VoiceSettings.Native.Advanced";

		private static readonly float[] RangePresets = new float[5] { 1f, 2f, 5f, 10f, 20f };

		private static readonly string[] RangeLabels = new string[5] { "VANILLA ×1", "SOCIAL ×2", "WIDE ×5", "FAR ×10", "MAXIMUM ×20" };

		private static readonly Dictionary<int, AudioScrollState> Scrollers = new Dictionary<int, AudioScrollState>();

		public static void Ensure()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			try
			{
				foreach (SettingsMenu item in Object.FindObjectsOfType<SettingsMenu>(true))
				{
					Attach(item);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource trace = Plugin.Trace;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(40, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not attach native Audio settings: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				trace.LogError(val);
			}
		}

		public static void Refresh()
		{
			foreach (SettingsMenu item in Object.FindObjectsOfType<SettingsMenu>(true))
			{
				Refresh(item);
			}
		}

		public static void Tick()
		{
			foreach (AudioScrollState value in Scrollers.Values)
			{
				value.Tick();
			}
		}

		private static void Attach(SettingsMenu menu)
		{
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Expected O, but got Unknown
			SettingsMenu obj = menu;
			SettingsCatagory val = ((obj != null) ? obj.catagoryAudio : null);
			if (((val != null) ? val.rows : null) == null || ((Il2CppArrayBase<SettingsRow>)(object)val.rows).Length == 0)
			{
				return;
			}
			Transform val2 = FindDescendant(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Positioning");
			if ((Object)(object)val2 != (Object)null)
			{
				EnsureScroller(menu, val2.parent);
				Refresh(menu);
				return;
			}
			SettingsRow val3 = FindCycleTemplate(val);
			if ((Object)(object)val3 == (Object)null)
			{
				return;
			}
			SettingsRow obj2 = FindSliderTemplate(val);
			Transform parent = ((Component)val3).transform.parent;
			int sibling = LastAudioSibling(val) + 1;
			List<SettingsRow> list = new List<SettingsRow>();
			SettingsRow val4 = CloneRow(val3, parent, sibling++, "BigWalk.VoiceSettings.Native.Positioning");
			ConfigureCycleRow(val4, "VOICE POSITIONING", () => (!Plugin.Instance.TwoDVoice.Value) ? "3D SPATIAL" : "2D EVERYWHERE", delegate
			{
				Plugin.Instance.TwoDVoice.Value = !Plugin.Instance.TwoDVoice.Value;
				ApplyAndRefresh();
			});
			list.Add(val4);
			if (obj2 == null)
			{
				obj2 = val3;
			}
			SettingsRow val5 = CloneRow(obj2, parent, sibling++, "BigWalk.VoiceSettings.Native.Range");
			if ((Object)(object)val5.slider != (Object)null)
			{
				ConfigureSliderRow(val5, "PROXIMITY RANGE", Plugin.Instance.RangeMultiplier.Value, delegate(float value)
				{
					Plugin.Instance.RangeMultiplier.Value = value;
					ApplyAndRefresh();
				});
			}
			else
			{
				ConfigureCycleRow(val5, "PROXIMITY RANGE", RangeLabel, delegate(int delta)
				{
					int num = ClosestRangeIndex(Plugin.Instance.RangeMultiplier.Value);
					num = (num + delta + RangePresets.Length) % RangePresets.Length;
					Plugin.Instance.RangeMultiplier.Value = RangePresets[num];
					ApplyAndRefresh();
				});
			}
			list.Add(val5);
			SettingsRow val6 = CloneRow(val3, parent, sibling++, "BigWalk.VoiceSettings.Native.Indicators");
			ConfigureCycleRow(val6, "SPEAKER INDICATORS", IndicatorLabel, delegate(int delta)
			{
				SetIndicatorIndex((IndicatorIndex() + delta + 3) % 3);
				Refresh();
			});
			list.Add(val6);
			SettingsRow val7 = FindButtonTemplate(menu);
			SettingsRow val8 = (((Object)(object)val7 != (Object)null) ? CloneRow(val7, parent, sibling, "BigWalk.VoiceSettings.Native.Advanced") : CloneRow(val3, parent, sibling, "BigWalk.VoiceSettings.Native.Advanced"));
			if ((Object)(object)val8.boringButton != (Object)null)
			{
				ConfigureButtonRow(val8, "BETTER PROXIMITY VOICE", "ADVANCED SETTINGS", delegate
				{
					Plugin.Instance.Overlay.OpenFromNativeSettings(menu);
				});
			}
			else
			{
				ConfigureCycleRow(val8, "ADVANCED VOICE SETTINGS", () => "OPEN", delegate
				{
					Plugin.Instance.Overlay.OpenFromNativeSettings(menu);
				});
			}
			list.Add(val8);
			RebuildNavigation(val, list);
			RectTransform val9 = AsRect(parent);
			if ((Object)(object)val9 != (Object)null)
			{
				LayoutRebuilder.ForceRebuildLayoutImmediate(val9);
			}
			EnsureScroller(menu, parent);
			Refresh(menu);
			ManualLogSource trace = Plugin.Trace;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val10 = new BepInExInfoLogInterpolatedStringHandler(47, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val10).AppendLiteral("Added native voice controls to ");
				((BepInExLogInterpolatedStringHandler)val10).AppendFormatted<string>(menu.isInMainMenu ? "main-menu" : "in-game");
				((BepInExLogInterpolatedStringHandler)val10).AppendLiteral(" Audio settings.");
			}
			trace.LogInfo(val10);
		}

		private static SettingsRow FindCycleTemplate(SettingsCatagory category)
		{
			foreach (SettingsRow item in (Il2CppArrayBase<SettingsRow>)(object)category.rows)
			{
				if ((Object)(object)item != (Object)null && (Object)(object)item.leftButton != (Object)null && (Object)(object)item.rightButton != (Object)null && (Object)(object)item.arrayLabel != (Object)null)
				{
					return item;
				}
			}
			return null;
		}

		private static SettingsRow FindSliderTemplate(SettingsCatagory category)
		{
			foreach (SettingsRow item in (Il2CppArrayBase<SettingsRow>)(object)category.rows)
			{
				if ((Object)(object)item != (Object)null && (Object)(object)item.slider != (Object)null && (Object)(object)item.sliderLabel != (Object)null)
				{
					return item;
				}
			}
			return null;
		}

		private static SettingsRow FindButtonTemplate(SettingsMenu menu)
		{
			SettingsCatagory[] array = (SettingsCatagory[])(object)new SettingsCatagory[4] { menu.catagoryAudio, menu.catagoryGeneral, menu.catagoryControls, menu.catagoryGraphics };
			foreach (SettingsCatagory val in array)
			{
				if (((val != null) ? val.rows : null) == null)
				{
					continue;
				}
				foreach (SettingsRow item in (Il2CppArrayBase<SettingsRow>)(object)val.rows)
				{
					if ((Object)(object)item != (Object)null && (Object)(object)item.boringButton != (Object)null)
					{
						return item;
					}
				}
			}
			return null;
		}

		private static int LastAudioSibling(SettingsCatagory category)
		{
			int num = 0;
			foreach (SettingsRow item in (Il2CppArrayBase<SettingsRow>)(object)category.rows)
			{
				if ((Object)(object)item != (Object)null)
				{
					num = Math.Max(num, ((Component)item).transform.GetSiblingIndex());
				}
			}
			return num;
		}

		private static SettingsRow CloneRow(SettingsRow template, Transform parent, int sibling, string name)
		{
			GameObject obj = Object.Instantiate<GameObject>(((Component)template).gameObject, parent);
			((Object)obj).name = name;
			obj.transform.SetSiblingIndex(sibling);
			obj.SetActive(true);
			SettingsRow component = obj.GetComponent<SettingsRow>();
			((Behaviour)component).enabled = false;
			component.settingsMenu = template.settingsMenu;
			return component;
		}

		private static void ConfigureCycleRow(SettingsRow row, string title, Func<string> value, Action<int> change)
		{
			SetRowTitle(row, title);
			SetRaw(row.arrayLabel, value());
			Wire(row.leftButton, delegate
			{
				change(-1);
			});
			Wire(row.rightButton, delegate
			{
				change(1);
			});
		}

		private static void ConfigureButtonRow(SettingsRow row, string title, string buttonText, Action action)
		{
			SetRowTitle(row, title);
			SetButtonText(row.boringButton, buttonText);
			Wire(row.boringButton, action);
		}

		private static void ConfigureSliderRow(SettingsRow row, string title, float value, Action<float> change)
		{
			SetRowTitle(row, title);
			row.slider.minValue = 1f;
			row.slider.maxValue = 20f;
			row.slider.wholeNumbers = true;
			row.slider.SetValueWithoutNotify(Mathf.Round(value));
			SetRaw(row.sliderLabel, $"×{Mathf.RoundToInt(value)}");
			int persistentEventCount = ((UnityEventBase)row.slider.onValueChanged).GetPersistentEventCount();
			for (int i = 0; i < persistentEventCount; i++)
			{
				((UnityEventBase)row.slider.onValueChanged).SetPersistentListenerState(i, (UnityEventCallState)0);
			}
			((UnityEventBase)row.slider.onValueChanged).RemoveAllListeners();
			((UnityEvent<float>)(object)row.slider.onValueChanged).AddListener(DelegateSupport.ConvertDelegate<UnityAction<float>>((Delegate)change));
		}

		private static void Wire(Button button, Action callback)
		{
			if (!((Object)(object)button == (Object)null))
			{
				int persistentEventCount = ((UnityEventBase)button.onClick).GetPersistentEventCount();
				for (int i = 0; i < persistentEventCount; i++)
				{
					((UnityEventBase)button.onClick).SetPersistentListenerState(i, (UnityEventCallState)0);
				}
				((UnityEventBase)button.onClick).RemoveAllListeners();
				((UnityEvent)button.onClick).AddListener(DelegateSupport.ConvertDelegate<UnityAction>((Delegate)callback));
			}
		}

		private static void Refresh(SettingsMenu menu)
		{
			if (!((Object)(object)menu == (Object)null))
			{
				SetCycleTitle(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Positioning", "VOICE POSITIONING");
				SetCycleValue(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Positioning", Plugin.Instance.TwoDVoice.Value ? "2D EVERYWHERE" : "3D SPATIAL");
				SetCycleTitle(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Range", "PROXIMITY RANGE");
				SetRangeValue(((Component)menu).transform);
				SetCycleTitle(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Indicators", "SPEAKER INDICATORS");
				SetCycleValue(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Indicators", IndicatorLabel());
				SetCycleTitle(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Advanced", "BETTER PROXIMITY VOICE");
				Transform obj = FindDescendant(((Component)menu).transform, "BigWalk.VoiceSettings.Native.Advanced");
				SettingsRow val = ((obj != null) ? ((Component)obj).GetComponent<SettingsRow>() : null);
				if ((Object)(object)((val != null) ? val.boringButton : null) != (Object)null)
				{
					SetButtonText(val.boringButton, "ADVANCED SETTINGS");
				}
				else if ((Object)(object)((val != null) ? val.arrayLabel : null) != (Object)null)
				{
					SetRaw(val.arrayLabel, "OPEN");
				}
			}
		}

		private static void SetCycleTitle(Transform menu, string name, string value)
		{
			Transform obj = FindDescendant(menu, name);
			SettingsRow val = ((obj != null) ? ((Component)obj).GetComponent<SettingsRow>() : null);
			if (!((Object)(object)val == (Object)null))
			{
				SetRowTitle(val, value);
			}
		}

		private static void SetCycleValue(Transform menu, string name, string value)
		{
			Transform obj = FindDescendant(menu, name);
			SettingsRow val = ((obj != null) ? ((Component)obj).GetComponent<SettingsRow>() : null);
			if ((Object)(object)((val != null) ? val.arrayLabel : null) != (Object)null)
			{
				SetRaw(val.arrayLabel, value);
			}
		}

		private static void SetRangeValue(Transform menu)
		{
			Transform obj = FindDescendant(menu, "BigWalk.VoiceSettings.Native.Range");
			SettingsRow val = ((obj != null) ? ((Component)obj).GetComponent<SettingsRow>() : null);
			if (!((Object)(object)val == (Object)null))
			{
				if ((Object)(object)val.slider != (Object)null)
				{
					float num = Mathf.Clamp(Plugin.Instance.RangeMultiplier.Value, 1f, 20f);
					val.slider.SetValueWithoutNotify(Mathf.Round(num));
					SetRaw(val.sliderLabel, $"×{num:0.##}");
				}
				else if ((Object)(object)val.arrayLabel != (Object)null)
				{
					SetRaw(val.arrayLabel, RangeLabel());
				}
			}
		}

		private static Transform FindDescendant(Transform root, string name)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			foreach (Transform componentsInChild in ((Component)root).GetComponentsInChildren<Transform>(true))
			{
				if ((Object)(object)componentsInChild != (Object)null && ((Object)((Component)componentsInChild).gameObject).name == name)
				{
					return componentsInChild;
				}
			}
			return null;
		}

		private static void RebuildNavigation(SettingsCatagory category, List<SettingsRow> customRows)
		{
			List<SettingsRow> list = new List<SettingsRow>();
			foreach (SettingsRow item in (Il2CppArrayBase<SettingsRow>)(object)category.rows)
			{
				if ((Object)(object)item != (Object)null)
				{
					list.Add(item);
				}
			}
			list.AddRange(customRows);
			for (int i = 0; i < list.Count; i++)
			{
				SettingsRow val = ((i == 0) ? null : list[i - 1]);
				SettingsRow val2 = ((i == list.Count - 1) ? null : list[i + 1]);
				list[i].SetNavigation(val, val2);
			}
		}

		private static void ApplyAndRefresh()
		{
			Plugin.Instance.Overlay.ApplyImmediately();
			Refresh();
		}

		private static string RangeLabel()
		{
			float value = Plugin.Instance.RangeMultiplier.Value;
			int num = ClosestRangeIndex(value);
			if (!(Mathf.Abs(RangePresets[num] - value) < 0.01f))
			{
				return $"CUSTOM ×{value:0.##}";
			}
			return RangeLabels[num];
		}

		private static int ClosestRangeIndex(float value)
		{
			int result = 0;
			float num = float.MaxValue;
			for (int i = 0; i < RangePresets.Length; i++)
			{
				float num2 = Mathf.Abs(RangePresets[i] - value);
				if (!(num2 >= num))
				{
					num = num2;
					result = i;
				}
			}
			return result;
		}

		private static int IndicatorIndex()
		{
			if (!Plugin.Instance.SpeakerIndicators.Value)
			{
				return 0;
			}
			if (!Plugin.Instance.ActiveSpeakerRoster.Value)
			{
				return 1;
			}
			return 2;
		}

		private static string IndicatorLabel()
		{
			return IndicatorIndex() switch
			{
				0 => "OFF", 
				1 => "ICONS", 
				_ => "ICONS + ROSTER", 
			};
		}

		private static void SetIndicatorIndex(int index)
		{
			Plugin.Instance.SpeakerIndicators.Value = index != 0;
			Plugin.Instance.ActiveSpeakerRoster.Value = index == 2;
		}

		private static void SetRaw(LocalizedText localized, string value)
		{
			if ((Object)(object)localized == (Object)null)
			{
				return;
			}
			localized.displayType = (DisplayType)1;
			localized.rawValue = value;
			localized.Change(value, (DisplayType)1);
			if ((Object)(object)localized.textElement != (Object)null)
			{
				localized.textElement.text = value;
			}
			foreach (TMP_Text componentsInChild in ((Component)localized).GetComponentsInChildren<TMP_Text>(true))
			{
				if ((Object)(object)componentsInChild != (Object)null)
				{
					componentsInChild.text = value;
				}
			}
		}

		private static void SetRowTitle(SettingsRow row, string value)
		{
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			SetRaw(row.title, value);
			LocalizedText arrayLabel = row.arrayLabel;
			TMP_Text val = ((arrayLabel != null) ? arrayLabel.textElement : null);
			LocalizedText sliderLabel = row.sliderLabel;
			TMP_Text val2 = ((sliderLabel != null) ? sliderLabel.textElement : null);
			foreach (TMP_Text componentsInChild in ((Component)row).GetComponentsInChildren<TMP_Text>(true))
			{
				if ((Object)(object)componentsInChild == (Object)null || (Object)(object)componentsInChild == (Object)(object)val || (Object)(object)componentsInChild == (Object)(object)val2)
				{
					continue;
				}
				Transform transform = componentsInChild.transform;
				Button leftButton = row.leftButton;
				if (IsWithin(transform, (leftButton != null) ? ((Component)leftButton).transform : null))
				{
					continue;
				}
				Transform transform2 = componentsInChild.transform;
				Button rightButton = row.rightButton;
				if (IsWithin(transform2, (rightButton != null) ? ((Component)rightButton).transform : null))
				{
					continue;
				}
				Transform transform3 = componentsInChild.transform;
				Button boringButton = row.boringButton;
				if (!IsWithin(transform3, (boringButton != null) ? ((Component)boringButton).transform : null))
				{
					LocalizedText component = ((Component)componentsInChild).GetComponent<LocalizedText>();
					if ((Object)(object)component != (Object)null)
					{
						((Behaviour)component).enabled = false;
						component.displayType = (DisplayType)1;
						component.rawValue = value;
					}
					componentsInChild.text = value;
				}
			}
		}

		private static bool IsWithin(Transform candidate, Transform ancestor)
		{
			if ((Object)(object)candidate == (Object)null || (Object)(object)ancestor == (Object)null)
			{
				return false;
			}
			Transform val = candidate;
			while ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)val == (Object)(object)ancestor)
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static void SetButtonText(Button button, string value)
		{
			TMP_Text val = ((button != null) ? ((Component)button).GetComponentInChildren<TMP_Text>(true) : null);
			if (!((Object)(object)val == (Object)null))
			{
				LocalizedText component = ((Component)val).GetComponent<LocalizedText>();
				if ((Object)(object)component != (Object)null)
				{
					SetRaw(component, value);
				}
				else
				{
					val.text = value;
				}
			}
		}

		private static void EnsureScroller(SettingsMenu menu, Transform contentTransform)
		{
			int instanceID = ((Object)menu).GetInstanceID();
			if (!Scrollers.ContainsKey(instanceID))
			{
				RectTransform val = AsRect(contentTransform);
				RectTransform val2 = AsRect(menu.contents);
				if ((Object)(object)val2 == (Object)null || (Object)(object)val2 == (Object)(object)val)
				{
					val2 = AsRect((contentTransform != null) ? contentTransform.parent : null);
				}
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val))
				{
					Scrollers[instanceID] = new AudioScrollState(menu, val, val2);
				}
			}
		}

		private static RectTransform AsRect(Transform transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return null;
			}
			RectTransform val = ((Il2CppObjectBase)transform).TryCast<RectTransform>();
			if (!((Object)(object)val != (Object)null))
			{
				return ((Component)transform).GetComponent<RectTransform>();
			}
			return val;
		}

		internal static bool IsCustomRow(SettingsRow row)
		{
			if ((Object)(object)row != (Object)null)
			{
				return ((Object)((Component)row).gameObject).name.StartsWith("BigWalk.VoiceSettings.Native.", StringComparison.Ordinal);
			}
			return false;
		}

		internal static void ResetToDefaults()
		{
			Plugin.Instance.RangeMultiplier.Value = 1f;
			Plugin.Instance.TwoDVoice.Value = false;
			Plugin.Instance.SpeakerIndicators.Value = true;
			Plugin.Instance.SpeakerNames.Value = true;
			Plugin.Instance.ActiveSpeakerRoster.Value = true;
			Plugin.Instance.SpeakerDistances.Value = true;
			Plugin.Instance.HudScale.Value = 1f;
			Plugin.Instance.TalkThreshold.Value = 0.004f;
			Plugin.Instance.Overlay.ApplyImmediately();
			Refresh();
		}
	}
	[HarmonyPatch(typeof(SettingsMenu), "ActionResetAudio")]
	internal static class AudioResetPatch
	{
		private static void Postfix()
		{
			NativeSettingsIntegration.ResetToDefaults();
		}
	}
	[HarmonyPatch(typeof(SettingsRow), "Refresh")]
	internal static class CustomSettingsRowRefreshPatch
	{
		private static bool Prefix(SettingsRow __instance)
		{
			if (!NativeSettingsIntegration.IsCustomRow(__instance))
			{
				return true;
			}
			NativeSettingsIntegration.Refresh();
			return false;
		}
	}
	internal static class PlayerVoiceInfo
	{
		public static string DisplayName(PlayerVoicePlaybackControl control, int fallbackIndex = 0)
		{
			try
			{
				object obj;
				if (control == null)
				{
					obj = null;
				}
				else
				{
					PlayerCharacter playerCharacter = control.playerCharacter;
					obj = ((playerCharacter != null) ? playerCharacter.playerNetworking : null);
				}
				PlayerNetworking val = (PlayerNetworking)obj;
				if ((Object)(object)val != (Object)null)
				{
					string text = FirstUseful(val.moderationNameSanitized, val.moderationName, val.username);
					if (text != null)
					{
						return text;
					}
				}
				string text2 = ((control != null) ? control.XProviderIdentifier : null);
				if (!string.IsNullOrWhiteSpace(text2))
				{
					return text2;
				}
			}
			catch
			{
			}
			if (fallbackIndex <= 0)
			{
				return "Unknown player";
			}
			return $"Player {fallbackIndex}";
		}

		public static Transform Anchor(PlayerVoicePlaybackControl control)
		{
			if ((Object)(object)control == (Object)null)
			{
				return null;
			}
			if (!((Object)(object)control.playerCharacter != (Object)null))
			{
				return ((Component)control).transform;
			}
			return ((Component)control.playerCharacter).transform;
		}

		public static float DistanceFromCamera(PlayerVoicePlaybackControl control)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			Transform val = Anchor(control);
			if (!((Object)(object)main != (Object)null) || !((Object)(object)val != (Object)null))
			{
				return -1f;
			}
			return Vector3.Distance(((Component)main).transform.position, val.position);
		}

		public static float AudibleRange(PlayerVoicePlaybackControl control)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			AnimationCurve val = ((control != null) ? control.AttenuationCurve : null);
			if (val == null)
			{
				return 0f;
			}
			Il2CppStructArray<Keyframe> keys = val.keys;
			if (keys == null || ((Il2CppArrayBase<Keyframe>)(object)keys).Length == 0)
			{
				return 0f;
			}
			Keyframe val2;
			for (int i = 0; i < ((Il2CppArrayBase<Keyframe>)(object)keys).Length; i++)
			{
				val2 = ((Il2CppArrayBase<Keyframe>)(object)keys)[i];
				if (Mathf.Abs(((Keyframe)(ref val2)).value) < 0.0001f)
				{
					val2 = ((Il2CppArrayBase<Keyframe>)(object)keys)[i];
					if (((Keyframe)(ref val2)).time > 0f)
					{
						val2 = ((Il2CppArrayBase<Keyframe>)(object)keys)[i];
						return ((Keyframe)(ref val2)).time;
					}
				}
			}
			val2 = ((Il2CppArrayBase<Keyframe>)(object)keys)[((Il2CppArrayBase<Keyframe>)(object)keys).Length - 1];
			return ((Keyframe)(ref val2)).time;
		}

		private static string FirstUseful(params string[] candidates)
		{
			foreach (string text in candidates)
			{
				if (!string.IsNullOrWhiteSpace(text))
				{
					return text.Trim();
				}
			}
			return null;
		}
	}
	[BepInPlugin("com.bigwalk.voicesettings", "Better Proximity Voice", "1.4.0")]
	public class Plugin : BasePlugin
	{
		public const string Guid = "com.bigwalk.voicesettings";

		public const string Version = "1.4.0";

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Trace { get; private set; }

		internal ConfigEntry<string> MenuShortcut { get; private set; }

		internal ConfigEntry<string> ToggleTwoDShortcut { get; private set; }

		internal ConfigEntry<string> CycleRangeShortcut { get; private set; }

		internal ConfigEntry<string> ToggleHudShortcut { get; private set; }

		internal ConfigEntry<bool> FreeCursor { get; private set; }

		internal ConfigEntry<float> RangeMultiplier { get; private set; }

		internal ConfigEntry<bool> TwoDVoice { get; private set; }

		internal ConfigEntry<bool> SpeakerIndicators { get; private set; }

		internal ConfigEntry<bool> SpeakerNames { get; private set; }

		internal ConfigEntry<bool> ActiveSpeakerRoster { get; private set; }

		internal ConfigEntry<bool> SpeakerDistances { get; private set; }

		internal ConfigEntry<float> HudScale { get; private set; }

		internal ConfigEntry<float> TalkThreshold { get; private set; }

		internal VoiceSettingsOverlay Overlay { get; private set; }

		public override void Load()
		{
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Expected O, but got Unknown
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Expected O, but got Unknown
			Instance = this;
			Trace = ((BasePlugin)this).Log;
			MenuShortcut = ((BasePlugin)this).Config.Bind<string>("Shortcuts", "OpenMenu", "LeftAlt + V", "Shows or hides Advanced Voice Settings. Core controls also appear in Settings > Audio.");
			ToggleTwoDShortcut = ((BasePlugin)this).Config.Bind<string>("Shortcuts", "ToggleAudioMode", "Not bound", "Optionally switches between positional 3D voice and non-positional 2D voice.");
			CycleRangeShortcut = ((BasePlugin)this).Config.Bind<string>("Shortcuts", "CycleRange", "Not bound", "Optionally cycles the voice-range presets: x1, x2, x5, x10, and x20.");
			ToggleHudShortcut = ((BasePlugin)this).Config.Bind<string>("Shortcuts", "ToggleHud", "Not bound", "Optionally shows or hides all speaker HUD elements.");
			FreeCursor = ((BasePlugin)this).Config.Bind<bool>("Menu", "FreeCursorWhenOpen", true, "Unlocks and shows the mouse cursor while the voice settings menu is open.");
			RangeMultiplier = ((BasePlugin)this).Config.Bind<float>("Voice", "RangeMultiplier", 1f, "Multiplies the distance over which you hear other players (1-20). This changes only your local playback.");
			TwoDVoice = ((BasePlugin)this).Config.Bind<bool>("Voice", "TwoDVoice", false, "Plays every received voice non-positionally and without distance attenuation.");
			SpeakerIndicators = ((BasePlugin)this).Config.Bind<bool>("Indicators", "Enabled", true, "Draws an icon over every remote player currently speaking.");
			SpeakerNames = ((BasePlugin)this).Config.Bind<bool>("Indicators", "ShowNames", true, "Shows each speaking player's display name beside their world indicator.");
			ActiveSpeakerRoster = ((BasePlugin)this).Config.Bind<bool>("Indicators", "ActiveSpeakerRoster", true, "Shows a compact roster of current speakers in the lower-right corner.");
			SpeakerDistances = ((BasePlugin)this).Config.Bind<bool>("Indicators", "ShowDistance", true, "Shows distance in metres beside each speaking player's name.");
			HudScale = ((BasePlugin)this).Config.Bind<float>("Indicators", "HudScale", 1f, "Scales speaker indicators and the active-speaker roster (0.75-1.5).");
			TalkThreshold = ((BasePlugin)this).Config.Bind<float>("Indicators", "TalkThreshold", 0.004f, "Minimum smoothed voice amplitude treated as speech. Lower this if quiet speakers do not light up; raise it if icons appear because of background noise.");
			RangeMultiplier.Value = Mathf.Clamp(RangeMultiplier.Value, 1f, 20f);
			HudScale.Value = Mathf.Clamp(HudScale.Value, 0.75f, 1.5f);
			TalkThreshold.Value = Mathf.Clamp(TalkThreshold.Value, 0.0001f, 0.1f);
			ClassInjector.RegisterTypeInIl2Cpp<VoiceSettingsOverlay>();
			new Harmony("com.bigwalk.voicesettings").PatchAll(typeof(Plugin).Assembly);
			GameObject val = new GameObject("BigWalk.VoiceSettings");
			((Object)val).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)val);
			Overlay = val.AddComponent<VoiceSettingsOverlay>();
			ManualLogSource log = ((BasePlugin)this).Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(77, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Loaded. Native controls appear in Settings > Audio; ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(MenuShortcut.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" opens advanced settings.");
			}
			log.LogInfo(val2);
		}
	}
	internal static class ShortcutBinding
	{
		private readonly struct Parsed
		{
			public KeyCode MainKey { get; }

			public KeyCode[] Modifiers { get; }

			public string Display { get; }

			public Parsed(KeyCode mainKey, KeyCode[] modifiers, string display)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				MainKey = mainKey;
				Modifiers = modifiers;
				Display = display;
			}
		}

		private static readonly HashSet<KeyCode> ModifierKeys = new HashSet<KeyCode>
		{
			(KeyCode)308,
			(KeyCode)307,
			(KeyCode)306,
			(KeyCode)305,
			(KeyCode)304,
			(KeyCode)303,
			(KeyCode)310,
			(KeyCode)309,
			(KeyCode)311,
			(KeyCode)312
		};

		public static bool IsDown(string value)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!TryParse(value, out var parsed) || (int)parsed.MainKey == 0)
			{
				return false;
			}
			if (!Input.GetKeyDown(parsed.MainKey))
			{
				return false;
			}
			KeyCode[] modifiers = parsed.Modifiers;
			for (int i = 0; i < modifiers.Length; i++)
			{
				if (!Input.GetKey(modifiers[i]))
				{
					return false;
				}
			}
			return true;
		}

		public static bool IsBound(string value)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			if (TryParse(value, out var parsed))
			{
				return (int)parsed.MainKey > 0;
			}
			return false;
		}

		public static bool IsValid(string value)
		{
			Parsed parsed;
			return TryParse(value, out parsed);
		}

		public static string Display(string value)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (!TryParse(value, out var parsed))
			{
				return "Invalid (" + value + ")";
			}
			if ((int)parsed.MainKey != 0)
			{
				return parsed.Display;
			}
			return "Not bound";
		}

		public static bool Equivalent(string left, string right)
		{
			if (!TryParse(left, out var parsed) || !TryParse(right, out var parsed2))
			{
				return false;
			}
			return string.Equals(parsed.Display, parsed2.Display, StringComparison.OrdinalIgnoreCase);
		}

		private unsafe static bool TryParse(string value, out Parsed parsed)
		{
			//IL_0056: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: 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)
			parsed = new Parsed((KeyCode)0, Array.Empty<KeyCode>(), "Not bound");
			if (string.IsNullOrWhiteSpace(value) || value.Trim().Equals("Not bound", StringComparison.OrdinalIgnoreCase) || value.Trim().Equals("None", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			string[] array = value.Split('+', StringSplitOptions.RemoveEmptyEntries);
			List<KeyCode> list = new List<KeyCode>();
			KeyCode val = (KeyCode)0;
			string[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				if (!Enum.TryParse<KeyCode>(ExpandAlias(array2[i].Trim()), ignoreCase: true, out KeyCode result) || (int)result == 0)
				{
					return false;
				}
				if (ModifierKeys.Contains(result))
				{
					if (!list.Contains(result))
					{
						list.Add(result);
					}
					continue;
				}
				if ((int)val == 0)
				{
					val = result;
					continue;
				}
				return false;
			}
			if ((int)val == 0)
			{
				return false;
			}
			list.Sort((KeyCode left, KeyCode right) => ((int)left).CompareTo((int)right));
			List<string> list2 = new List<string>();
			foreach (KeyCode item in list)
			{
				list2.Add(((object)item/*cast due to .constrained prefix*/).ToString());
			}
			list2.Add(((object)(*(KeyCode*)(&val))/*cast due to .constrained prefix*/).ToString());
			parsed = new Parsed(val, list.ToArray(), string.Join(" + ", list2));
			return true;
		}

		private static string ExpandAlias(string token)
		{
			if (token.Equals("Alt", StringComparison.OrdinalIgnoreCase))
			{
				return "LeftAlt";
			}
			if (token.Equals("Ctrl", StringComparison.OrdinalIgnoreCase) || token.Equals("Control", StringComparison.OrdinalIgnoreCase))
			{
				return "LeftControl";
			}
			if (token.Equals("Shift", StringComparison.OrdinalIgnoreCase))
			{
				return "LeftShift";
			}
			if (token.Equals("Cmd", StringComparison.OrdinalIgnoreCase) || token.Equals("Command", StringComparison.OrdinalIgnoreCase))
			{
				return "LeftCommand";
			}
			return token;
		}
	}
	internal static class SpeakerIndicators
	{
		private sealed class ActiveSpeaker
		{
			public string Name;

			public float Level;

			public float Distance;
		}

		private const float BarGain = 12f;

		private const float HeadHeight = 2.4f;

		private static readonly List<ActiveSpeaker> ActiveSpeakers = new List<ActiveSpeaker>();

		private static Texture2D _pixel;

		private static GUIStyle _nameStyle;

		private static GUIStyle _rosterNameStyle;

		private static GUIStyle _rosterHeadingStyle;

		private static float _styledScale = -1f;

		private static Texture2D Pixel
		{
			get
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Expected O, but got Unknown
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_pixel != (Object)null)
				{
					return _pixel;
				}
				_pixel = new Texture2D(1, 1, (TextureFormat)4, false);
				_pixel.SetPixel(0, 0, Color.white);
				_pixel.Apply();
				((Object)_pixel).hideFlags = (HideFlags)61;
				return _pixel;
			}
		}

		public static bool IsTalking(PlayerVoicePlaybackControl control)
		{
			if ((Object)(object)control == (Object)null)
			{
				return false;
			}
			float num = Mathf.Clamp(Plugin.Instance.TalkThreshold.Value, 0.0001f, 0.1f);
			return control.SmoothedARV >= num;
		}

		public static void Draw()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Expected O, but got Unknown
			//IL_01e6: 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_005d: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			Color color = GUI.color;
			try
			{
				Camera main = Camera.main;
				List<PlayerVoicePlaybackControl> controls = PlayerVoicePlaybackControl.controls;
				if ((Object)(object)main == (Object)null || controls == null)
				{
					return;
				}
				float scale = Mathf.Clamp(Plugin.Instance.HudScale.Value, 0.75f, 1.5f);
				EnsureStyles(scale);
				ActiveSpeakers.Clear();
				Vector3 position = ((Component)main).transform.position;
				int num = 0;
				Enumerator<PlayerVoicePlaybackControl> enumerator = controls.GetEnumerator();
				while (enumerator.MoveNext())
				{
					PlayerVoicePlaybackControl current = enumerator.Current;
					if ((Object)(object)current == (Object)null)
					{
						continue;
					}
					num++;
					if (IsTalking(current))
					{
						Transform val = PlayerVoiceInfo.Anchor(current);
						if (!((Object)(object)val == (Object)null))
						{
							float level = Mathf.Clamp01(current.SmoothedARV * 12f);
							float num2 = Vector3.Distance(position, val.position);
							string name = PlayerVoiceInfo.DisplayName(current, num);
							Vector3 world = val.position + Vector3.up * 2.4f;
							float num3 = PlayerVoiceInfo.AudibleRange(current);
							float distanceRatio = ((num3 > 0f) ? Mathf.Clamp01(num2 / num3) : 0f);
							DrawMarker(main, world, distanceRatio, level, name, num2, scale);
							ActiveSpeakers.Add(new ActiveSpeaker
							{
								Name = name,
								Level = level,
								Distance = num2
							});
						}
					}
				}
				if (Plugin.Instance.ActiveSpeakerRoster.Value && ActiveSpeakers.Count > 0)
				{
					ActiveSpeakers.Sort((ActiveSpeaker left, ActiveSpeaker right) => right.Level.CompareTo(left.Level));
					DrawRoster(scale);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource trace = Plugin.Trace;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(27, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Speaker indicators failed: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				trace.LogError(val2);
			}
			finally
			{
				GUI.color = color;
			}
		}

		private static void DrawMarker(Camera camera, Vector3 world, float distanceRatio, float level, string name, float distance, float scale)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = camera.WorldToScreenPoint(world);
			bool num = val.z <= 0f;
			float num2 = 32f * scale;
			float num3 = (num ? ((float)Screen.width - val.x) : val.x);
			float num4 = (num ? 0f : ((float)Screen.height - val.y));
			bool offScreen = num || num3 < num2 || num3 > (float)Screen.width - num2 || num4 < num2 || num4 > (float)Screen.height - num2;
			num3 = Mathf.Clamp(num3, num2, (float)Screen.width - num2);
			num4 = Mathf.Clamp(num4, num2, (float)Screen.height - num2);
			Color colour = DistanceColour(distanceRatio);
			colour.a = Mathf.Lerp(1f, 0.42f, distanceRatio);
			DrawSpeaker(num3, num4, colour, level, offScreen, scale);
			if (Plugin.Instance.SpeakerNames.Value)
			{
				DrawName(num3, num4, name, distance, colour, scale);
			}
		}

		private static void DrawSpeaker(float centreX, float centreY, Color colour, float level, bool offScreen, float scale)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			GUI.color = new Color(0.025f, 0.03f, 0.035f, colour.a * 0.92f);
			Fill(centreX - 14f * scale, centreY - 12f * scale, 31f * scale, 24f * scale);
			GUI.color = colour;
			Fill(centreX - 10f * scale, centreY - 3f * scale, 4f * scale, 6f * scale);
			Fill(centreX - 6f * scale, centreY - 5f * scale, 2f * scale, 10f * scale);
			Fill(centreX - 4f * scale, centreY - 7f * scale, 2f * scale, 14f * scale);
			Fill(centreX - 2f * scale, centreY - 9f * scale, 2f * scale, 18f * scale);
			for (int i = 0; i < 3; i++)
			{
				Color color = colour;
				if (level < 0.15f + (float)i * 0.28f)
				{
					color.a *= 0.18f;
				}
				GUI.color = color;
				float num = (6f + (float)i * 4f) * scale;
				Fill(centreX + (3f + (float)i * 4f) * scale, centreY - num * 0.5f, 2f * scale, num);
			}
			if (offScreen)
			{
				GUI.color = colour;
				Fill(centreX - 8f * scale, centreY + 15f * scale, 16f * scale, 2f * scale);
			}
		}

		private static void DrawName(float markerX, float markerY, string name, float distance, Color colour, float scale)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_011f: Unknown result type (might be due to invalid IL or missing references)
			GUIContent val = new GUIContent(Plugin.Instance.SpeakerDistances.Value ? $"{name}  ·  {distance:0} m" : name);
			float num = Mathf.Min(_nameStyle.CalcSize(val).x + 18f * scale, 260f * scale);
			float num2 = 27f * scale;
			float num3 = markerX + 21f * scale;
			if (num3 + num > (float)Screen.width - 12f * scale)
			{
				num3 = markerX - num - 21f * scale;
			}
			float num4 = markerY - num2 * 0.5f;
			GUI.color = new Color(0.025f, 0.03f, 0.035f, 0.88f);
			Fill(num3, num4, num, num2);
			GUI.color = colour;
			Fill(num3, num4, 3f * scale, num2);
			GUI.color = Color.white;
			GUI.Label(new Rect(num3 + 10f * scale, num4, num - 14f * scale, num2), val, _nameStyle);
		}

		private static void DrawRoster(float scale)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Min(ActiveSpeakers.Count, 6);
			float num2 = 270f * scale;
			float num3 = 29f * scale;
			float num4 = 34f * scale;
			float num5 = num3 + (float)num * num4 + 8f * scale;
			float num6 = (float)Screen.width - num2 - 24f * scale;
			float num7 = (float)Screen.height - num5 - 24f * scale;
			GUI.color = new Color(0.025f, 0.03f, 0.035f, 0.88f);
			Fill(num6, num7, num2, num5);
			GUI.color = new Color(0.35f, 0.9f, 0.58f, 1f);
			Fill(num6, num7, 4f * scale, num5);
			GUI.color = Color.white;
			GUI.Label(new Rect(num6 + 13f * scale, num7, num2 - 20f * scale, num3), "NOW SPEAKING", _rosterHeadingStyle);
			for (int i = 0; i < num; i++)
			{
				ActiveSpeaker activeSpeaker = ActiveSpeakers[i];
				float num8 = num7 + num3 + (float)i * num4;
				string text = (Plugin.Instance.SpeakerDistances.Value ? $"{activeSpeaker.Distance:0} m" : "");
				GUI.color = Color.white;
				GUI.Label(new Rect(num6 + 13f * scale, num8, num2 - 75f * scale, 22f * scale), activeSpeaker.Name, _rosterNameStyle);
				GUI.Label(new Rect(num6 + num2 - 65f * scale, num8, 52f * scale, 22f * scale), text, _rosterNameStyle);
				GUI.color = new Color(1f, 1f, 1f, 0.15f);
				Fill(num6 + 13f * scale, num8 + 23f * scale, num2 - 26f * scale, 3f * scale);
				GUI.color = DistanceColour(1f - activeSpeaker.Level);
				Fill(num6 + 13f * scale, num8 + 23f * scale, (num2 - 26f * scale) * Mathf.Max(0.05f, activeSpeaker.Level), 3f * scale);
			}
		}

		private static Color DistanceColour(float ratio)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			ratio = Mathf.Clamp01(ratio);
			if (!(ratio < 0.5f))
			{
				return Color.Lerp(new Color(1f, 0.85f, 0.2f), new Color(1f, 0.25f, 0.2f), (ratio - 0.5f) * 2f);
			}
			return Color.Lerp(new Color(0.3f, 1f, 0.35f), new Color(1f, 0.85f, 0.2f), ratio * 2f);
		}

		private static void EnsureStyles(float scale)
		{
			if (_nameStyle == null || !Mathf.Approximately(scale, _styledScale))
			{
				_styledScale = scale;
				_nameStyle = NewLabel(Mathf.RoundToInt(14f * scale), (FontStyle)1, (TextAnchor)3);
				_rosterNameStyle = NewLabel(Mathf.RoundToInt(13f * scale), (FontStyle)0, (TextAnchor)0);
				_rosterHeadingStyle = NewLabel(Mathf.RoundToInt(12f * scale), (FontStyle)1, (TextAnchor)3);
			}
		}

		private static GUIStyle NewLabel(int fontSize, FontStyle fontStyle, TextAnchor alignment)
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				fontSize = fontSize,
				fontStyle = fontStyle,
				alignment = alignment,
				clipping = (TextClipping)1
			};
			val.normal.textColor = Color.white;
			return val;
		}

		private static void Fill(float x, float y, float width, float height)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			GUI.DrawTexture(new Rect(x, y, width, height), (Texture)(object)Pixel);
		}
	}
	internal static class VoiceRangeScaler
	{
		private sealed class Baseline
		{
			public Keyframe[] Attenuation;

			public Keyframe[] SpatialVolume;

			public Keyframe[] FilterDistance;

			public float SourceMaxDistance = -1f;
		}

		public const float MaxScale = 20f;

		private static readonly Dictionary<int, Baseline> Baselines = new Dictionary<int, Baseline>();

		private static float _scale = 1f;

		public static float Scale
		{
			get
			{
				return _scale;
			}
			set
			{
				_scale = Mathf.Clamp(value, 1f, 20f);
			}
		}

		public static int LastApplied { get; private set; }

		public static void Apply()
		{
			List<PlayerVoicePlaybackControl> controls = PlayerVoicePlaybackControl.controls;
			LastApplied = 0;
			if (controls == null)
			{
				return;
			}
			HashSet<int> hashSet = new HashSet<int>();
			Enumerator<PlayerVoicePlaybackControl> enumerator = controls.GetEnumerator();
			while (enumerator.MoveNext())
			{
				PlayerVoicePlaybackControl current = enumerator.Current;
				if (!((Object)(object)current == (Object)null))
				{
					int instanceID = ((Object)current).GetInstanceID();
					hashSet.Add(instanceID);
					if (!Baselines.TryGetValue(instanceID, out var value))
					{
						value = Capture(current);
						Baselines[instanceID] = value;
					}
					current.AttenuationCurve = Rescale(value.Attenuation, _scale);
					current.SpatialVolCurve = Rescale(value.SpatialVolume, _scale);
					current.FilterDistanceCurve = Rescale(value.FilterDistance, _scale);
					AudioSource val = SourceOf(current);
					if (value.SourceMaxDistance <= 0f && (Object)(object)val != (Object)null)
					{
						value.SourceMaxDistance = val.maxDistance;
					}
					if (value.SourceMaxDistance > 0f && (Object)(object)val != (Object)null)
					{
						val.maxDistance = value.SourceMaxDistance * _scale;
					}
					LastApplied++;
				}
			}
			if (Baselines.Count <= hashSet.Count)
			{
				return;
			}
			List<int> list = new List<int>();
			foreach (KeyValuePair<int, Baseline> baseline in Baselines)
			{
				if (!hashSet.Contains(baseline.Key))
				{
					list.Add(baseline.Key);
				}
			}
			foreach (int item in list)
			{
				Baselines.Remove(item);
			}
		}

		private static Baseline Capture(PlayerVoicePlaybackControl control)
		{
			Baseline baseline = new Baseline
			{
				Attenuation = Copy(control.AttenuationCurve),
				SpatialVolume = Copy(control.SpatialVolCurve),
				FilterDistance = Copy(control.FilterDistanceCurve)
			};
			AudioSource val = SourceOf(control);
			if ((Object)(object)val != (Object)null)
			{
				baseline.SourceMaxDistance = val.maxDistance;
			}
			return baseline;
		}

		private static AudioSource SourceOf(PlayerVoicePlaybackControl control)
		{
			try
			{
				AudioSourceController sourceController = control.SourceController;
				return ((Object)(object)sourceController != (Object)null) ? sourceController.AudioSource : null;
			}
			catch
			{
				return null;
			}
		}

		private static Keyframe[] Copy(AnimationCurve curve)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (curve == null)
			{
				return null;
			}
			Il2CppStructArray<Keyframe> keys = curve.keys;
			if (keys == null || ((Il2CppArrayBase<Keyframe>)(object)keys).Length == 0)
			{
				return null;
			}
			Keyframe[] array = (Keyframe[])(object)new Keyframe[((Il2CppArrayBase<Keyframe>)(object)keys).Length];
			for (int i = 0; i < ((Il2CppArrayBase<Keyframe>)(object)keys).Length; i++)
			{
				array[i] = ((Il2CppArrayBase<Keyframe>)(object)keys)[i];
			}
			return array;
		}

		private static AnimationCurve Rescale(Keyframe[] baseline, float scale)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			if (baseline == null || baseline.Length == 0)
			{
				return null;
			}
			Il2CppStructArray<Keyframe> val = new Il2CppStructArray<Keyframe>((long)baseline.Length);
			for (int i = 0; i < baseline.Length; i++)
			{
				Keyframe val2 = baseline[i];
				((Keyframe)(ref val2)).time = ((Keyframe)(ref val2)).time * scale;
				((Keyframe)(ref val2)).inTangent = ((Keyframe)(ref val2)).inTangent / scale;
				((Keyframe)(ref val2)).outTangent = ((Keyframe)(ref val2)).outTangent / scale;
				((Il2CppArrayBase<Keyframe>)(object)val)[i] = val2;
			}
			return new AnimationCurve(val);
		}
	}
	public class VoiceSettingsOverlay : MonoBehaviour
	{
		private enum ShortcutSlot
		{
			None,
			Menu,
			AudioMode,
			Range,
			Hud
		}

		private const float ApplyInterval = 1f;

		private static readonly float[] RangePresets = new float[5] { 1f, 2f, 5f, 10f, 20f };

		private bool _visible;

		private Rect _window = new Rect(24f, 24f, 620f, 480f);

		private Vector2 _scroll;

		private CursorLockMode _previousLockState = (CursorLockMode)1;

		private bool _previousCursorVisible;

		private float _nextApply;

		private string _rangeText;

		private string _status = "Waiting for a world…";

		private string _toastTitle;

		private string _toastDetail;

		private float _toastUntil;

		private ShortcutSlot _capturingShortcut;

		private SettingsMenu _returnToSettingsMenu;

		private Texture2D _panelTexture;

		private Texture2D _accentTexture;

		private GUIStyle _windowStyle;

		private GUIStyle _headingStyle;

		private GUIStyle _labelStyle;

		private GUIStyle _mutedLabelStyle;

		private GUIStyle _buttonStyle;

		private GUIStyle _selectedButtonStyle;

		private GUIStyle _toggleStyle;

		private GUIStyle _textFieldStyle;

		private GUIStyle _toastTitleStyle;

		public VoiceSettingsOverlay(IntPtr pointer)
			: base(pointer)
		{
		}//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)


		private void Start()
		{
			ApplySettings();
		}

		private void Update()
		{
			NativeSettingsIntegration.Tick();
			if (_capturingShortcut == ShortcutSlot.None)
			{
				if (_visible && Input.GetKeyDown((KeyCode)27))
				{
					SetVisible(visible: false);
					return;
				}
				if (ShortcutBinding.IsDown(Plugin.Instance.MenuShortcut.Value))
				{
					SetVisible(!_visible);
				}
				if (ShortcutBinding.IsDown(Plugin.Instance.ToggleTwoDShortcut.Value))
				{
					SetTwoD(!Plugin.Instance.TwoDVoice.Value, notify: true);
				}
				if (ShortcutBinding.IsDown(Plugin.Instance.CycleRangeShortcut.Value))
				{
					CycleRange();
				}
				if (ShortcutBinding.IsDown(Plugin.Instance.ToggleHudShortcut.Value))
				{
					Plugin.Instance.SpeakerIndicators.Value = !Plugin.Instance.SpeakerIndicators.Value;
					ShowToast(Plugin.Instance.SpeakerIndicators.Value ? "SPEAKER HUD ON" : "SPEAKER HUD OFF", Plugin.Instance.SpeakerIndicators.Value ? "Named talker indicators are visible." : "All speaker overlays are hidden.");
				}
			}
			if (_visible && Plugin.Instance.FreeCursor.Value)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
			if (!(Time.unscaledTime < _nextApply))
			{
				_nextApply = Time.unscaledTime + 1f;
				NativeSettingsIntegration.Ensure();
				ApplySettings();
			}
		}

		private void OnGUI()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Instance.SpeakerIndicators.Value && (int)Event.current.type == 7)
			{
				SpeakerIndicators.Draw();
			}
			if (_visible || !(Time.unscaledTime >= _toastUntil))
			{
				EnsureStyles();
				if (Time.unscaledTime < _toastUntil)
				{
					DrawToast();
				}
				if (_visible)
				{
					_window = GUI.Window(45430, _window, WindowFunction.op_Implicit((Action<int>)DrawWindow), "Better Proximity Voice", _windowStyle);
				}
			}
		}

		private void DrawWindow(int windowId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_077a: Unknown result type (might be due to invalid IL or missing references)
			Color color = GUI.color;
			GUI.color = Color.white;
			GUI.DrawTexture(new Rect(5f, 24f, ((Rect)(ref _window)).width - 10f, ((Rect)(ref _window)).height - 29f), (Texture)(object)_panelTexture);
			HandleShortcutCapture(Event.current);
			_scroll = GUILayout.BeginScrollView(_scroll, (Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label("Audio mode", _headingStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label("Choose positional awareness or maximum intelligibility.", _mutedLabelStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUIStyle val = (Plugin.Instance.TwoDVoice.Value ? _buttonStyle : _selectedButtonStyle);
			GUIStyle val2 = (Plugin.Instance.TwoDVoice.Value ? _selectedButtonStyle : _buttonStyle);
			if (GUILayout.Button("3D SPATIAL\nDirection + distance", val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(52f) }))
			{
				SetTwoD(enabled: false, notify: true);
			}
			if (GUILayout.Button("2D EVERYWHERE\nCentred + no distance fade", val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(52f) }))
			{
				SetTwoD(enabled: true, notify: true);
			}
			GUILayout.EndHorizontal();
			GUILayout.Label("Hearing range", _headingStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label("Client-side only. Other players need no mod.", _mutedLabelStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			float scale = VoiceRangeScaler.Scale;
			float num = Mathf.Log(20f);
			float num2 = Mathf.Log(Mathf.Max(scale, 1f)) / num;
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label("Range ×", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) });
			float num3 = GUILayout.HorizontalSlider(num2, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(350f) });
			GUILayout.Label(scale.ToString("0.##"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) });
			GUILayout.EndHorizontal();
			if (!Mathf.Approximately(num3, num2))
			{
				SetRange(Mathf.Exp(num3 * num));
			}
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			if (PresetButton("VANILLA", 1f))
			{
				SetRange(1f, notify: true);
			}
			if (PresetButton("SOCIAL", 2f))
			{
				SetRange(2f, notify: true);
			}
			if (PresetButton("WIDE", 5f))
			{
				SetRange(5f, notify: true);
			}
			if (PresetButton("FAR", 10f))
			{
				SetRange(10f, notify: true);
			}
			if (PresetButton("MAX", 20f))
			{
				SetRange(20f, notify: true);
			}
			GUILayout.EndHorizontal();
			GUILayout.Label(EffectiveRangeDescription(), _mutedLabelStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label("Exact", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) });
			_rangeText = GUILayout.TextField(_rangeText ?? scale.ToString("0.##", CultureInfo.InvariantCulture), _textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) });
			if (GUILayout.Button("Apply", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				if (float.TryParse(_rangeText, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					SetRange(result, notify: true);
				}
				else
				{
					_status = "'" + _rangeText + "' is not a number.";
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.Label("Speaker HUD", _headingStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			bool flag = GUILayout.Toggle(Plugin.Instance.SpeakerIndicators.Value, "Enabled", _toggleStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			if (flag != Plugin.Instance.SpeakerIndicators.Value)
			{
				Plugin.Instance.SpeakerIndicators.Value = flag;
			}
			bool flag2 = GUILayout.Toggle(Plugin.Instance.SpeakerNames.Value, "Names above talking players", _toggleStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			if (flag2 != Plugin.Instance.SpeakerNames.Value)
			{
				Plugin.Instance.SpeakerNames.Value = flag2;
			}
			bool flag3 = GUILayout.Toggle(Plugin.Instance.ActiveSpeakerRoster.Value, "Active-speaker roster", _toggleStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			if (flag3 != Plugin.Instance.ActiveSpeakerRoster.Value)
			{
				Plugin.Instance.ActiveSpeakerRoster.Value = flag3;
			}
			bool flag4 = GUILayout.Toggle(Plugin.Instance.SpeakerDistances.Value, "Show distance in metres", _toggleStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			if (flag4 != Plugin.Instance.SpeakerDistances.Value)
			{
				Plugin.Instance.SpeakerDistances.Value = flag4;
			}
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label("HUD size", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) });
			float num4 = GUILayout.HorizontalSlider(Plugin.Instance.HudScale.Value, 0.75f, 1.5f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(350f) });
			GUILayout.Label($"{num4:0.00}×", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) });
			GUILayout.EndHorizontal();
			if (!Mathf.Approximately(num4, Plugin.Instance.HudScale.Value))
			{
				Plugin.Instance.HudScale.Value = num4;
			}
			float num5 = Mathf.Clamp(Plugin.Instance.TalkThreshold.Value, 0.0005f, 0.02f);
			float num6 = 1f - Mathf.Log(num5 / 0.0005f) / Mathf.Log(39.999996f);
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label("Sensitivity", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) });
			float num7 = GUILayout.HorizontalSlider(num6, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(350f) });
			GUILayout.Label(SensitivityLabel(num7), _mutedLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) });
			GUILayout.EndHorizontal();
			if (!Mathf.Approximately(num7, num6))
			{
				Plugin.Instance.TalkThreshold.Value = 0.0005f * Mathf.Pow(39.999996f, 1f - num7);
			}
			GUILayout.Label("Quick controls", _headingStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label("Click a binding, then press the new shortcut. Escape cancels; Delete clears.", _mutedLabelStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			DrawShortcutRow(ShortcutSlot.Menu);
			DrawShortcutRow(ShortcutSlot.AudioMode);
			DrawShortcutRow(ShortcutSlot.Range);
			DrawShortcutRow(ShortcutSlot.Hud);
			string text = FindShortcutConflict();
			if (text != null)
			{
				GUILayout.Label("⚠ " + text, _labelStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			}
			else
			{
				GUILayout.Label("Optional shortcuts are unbound by default to avoid mod conflicts.", _mutedLabelStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			}
			GUILayout.Space(10f);
			DrawTalkers();
			GUILayout.EndScrollView();
			GUILayout.Space(5f);
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label(_status, _labelStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			if (GUILayout.Button("Reset", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				ResetDefaults();
			}
			if (GUILayout.Button("Close", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				SetVisible(visible: false);
			}
			GUILayout.EndHorizontal();
			GUI.color = color;
			GUI.DragWindow();
		}

		private void DrawTalkers()
		{
			List<PlayerVoicePlaybackControl> controls = PlayerVoicePlaybackControl.controls;
			if (controls == null || controls.Count == 0)
			{
				GUILayout.Label("Players", _headingStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
				GUILayout.Label("No remote voice players yet.", _labelStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
				return;
			}
			GUILayout.Label($"Players ({controls.Count})", _headingStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
			int num = 0;
			Enumerator<PlayerVoicePlaybackControl> enumerator = controls.GetEnumerator();
			while (enumerator.MoveNext())
			{
				PlayerVoicePlaybackControl current = enumerator.Current;
				if (!((Object)(object)current == (Object)null))
				{
					num++;
					string text = PlayerVoiceInfo.DisplayName(current, num);
					bool flag = SpeakerIndicators.IsTalking(current);
					float num2 = PlayerVoiceInfo.DistanceFromCamera(current);
					string text2 = ((num2 >= 0f) ? $"{num2:0} m" : "—");
					GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
					GUILayout.Label(flag ? "● TALKING" : "○ quiet", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) });
					GUILayout.Label(text, _labelStyle, (Il2CppReferenceArray<GUILayoutOption>)null);
					GUILayout.Label(text2, _mutedLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) });
					GUILayout.EndHorizontal();
				}
			}
		}

		private void EnsureStyles()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0081: 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_00c7: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Expected O, but got Unknown
			//IL_0181: Expected O, but got Unknown
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Expected O, but got Unknown
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Expected O, but got Unknown
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: 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_0244: Expected O, but got Unknown
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Expected O, but got Unknown
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Expected O, but got Unknown
			//IL_02b7: Expected O, but got Unknown
			if (_labelStyle == null)
			{
				_panelTexture = new Texture2D(1, 1, (TextureFormat)4, false);
				_panelTexture.SetPixel(0, 0, new Color(0.055f, 0.065f, 0.075f, 0.97f));
				_panelTexture.Apply();
				((Object)_panelTexture).hideFlags = (HideFlags)61;
				_accentTexture = new Texture2D(1, 1, (TextureFormat)4, false);
				_accentTexture.SetPixel(0, 0, new Color(0.12f, 0.42f, 0.27f, 1f));
				_accentTexture.Apply();
				((Object)_accentTexture).hideFlags = (HideFlags)61;
				_windowStyle = new GUIStyle(GUI.skin.window)
				{
					fontSize = 17,
					fontStyle = (FontStyle)1
				};
				SetTextColour(_windowStyle, Color.white);
				_labelStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16,
					wordWrap = true
				};
				SetTextColour(_labelStyle, new Color(0.93f, 0.95f, 0.97f));
				_mutedLabelStyle = new GUIStyle(_labelStyle)
				{
					fontSize = 14
				};
				SetTextColour(_mutedLabelStyle, new Color(0.67f, 0.72f, 0.76f));
				_headingStyle = new GUIStyle(_labelStyle)
				{
					fontSize = 18,
					fontStyle = (FontStyle)1,
					margin = new RectOffset(4, 4, 8, 3)
				};
				_buttonStyle = new GUIStyle(GUI.skin.button)
				{
					fontSize = 15,
					fixedHeight = 0f
				};
				SetTextColour(_buttonStyle, Color.white);
				_selectedButtonStyle = new GUIStyle(_buttonStyle);
				_selectedButtonStyle.normal.background = _accentTexture;
				_selectedButtonStyle.hover.background = _accentTexture;
				_selectedButtonStyle.active.background = _accentTexture;
				SetTextColour(_selectedButtonStyle, Color.white);
				_toggleStyle = new GUIStyle(GUI.skin.toggle)
				{
					fontSize = 16,
					fixedHeight = 28f
				};
				SetTextColour(_toggleStyle, Color.white);
				_textFieldStyle = new GUIStyle(GUI.skin.textField)
				{
					fontSize = 16,
					fixedHeight = 28f
				};
				SetTextColour(_textFieldStyle, Color.white);
				_toastTitleStyle = new GUIStyle(_headingStyle)
				{
					alignment = (TextAnchor)3,
					fontSize = 16,
					margin = new RectOffset()
				};
			}
		}

		private static void SetTextColour(GUIStyle style, Color colour)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			style.normal.textColor = colour;
			style.hover.textColor = colour;
			style.active.textColor = colour;
			style.focused.textColor = colour;
			style.onNormal.textColor = colour;
			style.onHover.textColor = colour;
			style.onActive.textColor = colour;
			style.onFocused.textColor = colour;
		}

		private bool PresetButton(string label, float value)
		{
			bool flag = Mathf.Abs(VoiceRangeScaler.Scale - value) < 0.01f;
			return GUILayout.Button($"{label}\n×{value:0}", flag ? _selectedButtonStyle : _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(46f) });
		}

		private static string SensitivityLabel(float value)
		{
			if (value < 0.25f)
			{
				return "Low";
			}
			if (value < 0.7f)
			{
				return "Normal";
			}
			return "High";
		}

		private static string ShortcutName(string shortcut)
		{
			return ShortcutBinding.Display(shortcut);
		}

		private void DrawShortcutRow(ShortcutSlot slot)
		{
			string text = ShortcutActionName(slot);
			ConfigEntry<string> val = ShortcutEntry(slot);
			bool flag = _capturingShortcut == slot;
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label(text, _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
			if (GUILayout.Button(flag ? "Press a shortcut…" : ShortcutName(val.Value), flag ? _selectedButtonStyle : _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				_capturingShortcut = slot;
				GUI.FocusControl((string)null);
				_status = "Listening for " + text.ToLowerInvariant() + " shortcut…";
			}
			if (GUILayout.Button("Clear", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(65f),
				GUILayout.Height(30f)
			}))
			{
				val.Value = "Not bound";
				if (flag)
				{
					_capturingShortcut = ShortcutSlot.None;
				}
				_status = text + " shortcut cleared.";
			}
			GUILayout.EndHorizontal();
		}

		private void HandleShortcutCapture(Event currentEvent)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Invalid comparison between Unknown and I4
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Invalid comparison between Unknown and I4
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (_capturingShortcut == ShortcutSlot.None || currentEvent == null || (int)currentEvent.type != 4)
			{
				return;
			}
			KeyCode keyCode = currentEvent.keyCode;
			if (IsModifier(keyCode))
			{
				return;
			}
			if ((int)keyCode == 27)
			{
				_status = "Shortcut change cancelled.";
				_capturingShortcut = ShortcutSlot.None;
				currentEvent.Use();
				return;
			}
			ConfigEntry<string> val = ShortcutEntry(_capturingShortcut);
			string text = ShortcutActionName(_capturingShortcut);
			if ((int)keyCode == 127 || (int)keyCode == 8)
			{
				val.Value = "Not bound";
				_status = text + " shortcut cleared.";
			}
			else
			{
				if ((int)keyCode == 0)
				{
					return;
				}
				string shortcut = (val.Value = ShortcutFromEvent(currentEvent, keyCode));
				_status = text + ": " + ShortcutName(shortcut);
			}
			_capturingShortcut = ShortcutSlot.None;
			currentEvent.Use();
		}

		private unsafe static string ShortcutFromEvent(Event currentEvent, KeyCode mainKey)
		{
			List<string> list = new List<string>();
			if (currentEvent.control)
			{
				list.Add("LeftControl");
			}
			if (currentEvent.shift)
			{
				list.Add("LeftShift");
			}
			if (currentEvent.alt)
			{
				list.Add("LeftAlt");
			}
			if (currentEvent.command)
			{
				list.Add("LeftCommand");
			}
			list.Add(((object)(*(KeyCode*)(&mainKey))/*cast due to .constrained prefix*/).ToString());
			return string.Join(" + ", list);
		}

		private static bool IsModifier(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Invalid comparison between Unknown and I4
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Invalid comparison between Unknown and I4
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Invalid comparison between Unknown and I4
			if ((int)key != 308 && (int)key != 307 && (int)key != 306 && (int)key != 305 && (int)key != 304 && (int)key != 303 && (int)key != 310 && (int)key != 309 && (int)key != 311)
			{
				return (int)key == 312;
			}
			return true;
		}

		private static ConfigEntry<string> ShortcutEntry(ShortcutSlot slot)
		{
			return (ConfigEntry<string>)(slot switch
			{
				ShortcutSlot.Menu => Plugin.Instance.MenuShortcut, 
				ShortcutSlot.AudioMode => Plugin.Instance.ToggleTwoDShortcut, 
				ShortcutSlot.Range => Plugin.Instance.CycleRangeShortcut, 
				ShortcutSlot.Hud => Plugin.Instance.ToggleHudShortcut, 
				_ => throw new ArgumentOutOfRangeException("slot"), 
			});
		}

		private static string ShortcutActionName(ShortcutSlot slot)
		{
			return slot switch
			{
				ShortcutSlot.Menu => "Open menu", 
				ShortcutSlot.AudioMode => "2D / 3D", 
				ShortcutSlot.Range => "Cycle range", 
				ShortcutSlot.Hud => "Toggle HUD", 
				_ => "Shortcut", 
			};
		}

		private static string FindShortcutConflict()
		{
			(string, string)[] array = new(string, string)[4]
			{
				("Menu", Plugin.Instance.MenuShortcut.Value),
				("2D/3D", Plugin.Instance.ToggleTwoDShortcut.Value),
				("Cycle range", Plugin.Instance.CycleRangeShortcut.Value),
				("HUD", Plugin.Instance.ToggleHudShortcut.Value)
			};
			for (int i = 0; i < array.Length; i++)
			{
				if (!ShortcutBinding.IsBound(array[i].Item2))
				{
					continue;
				}
				for (int j = i + 1; j < array.Length; j++)
				{
					if (ShortcutBinding.IsBound(array[j].Item2) && ShortcutBinding.Equivalent(array[i].Item2, array[j].Item2))
					{
						return array[i].Item1 + " and " + array[j].Item1 + " use the same shortcut.";
					}
				}
			}
			(string, string)[] array2 = array;
			for (int k = 0; k < array2.Length; k++)
			{
				(string, string) tuple = array2[k];
				if (!ShortcutBinding.IsValid(tuple.Item2))
				{
					return tuple.Item1 + " has an invalid shortcut: '" + tuple.Item2 + "'.";
				}
			}
			return null;
		}

		private string EffectiveRangeDescription()
		{
			List<PlayerVoicePlaybackControl> controls = PlayerVoicePlaybackControl.controls;
			if (Plugin.Instance.TwoDVoice.Value)
			{
				return "2D mode bypasses positional distance fade.";
			}
			if (controls == null)
			{
				return "Effective distance appears after another player joins.";
			}
			Enumerator<PlayerVoicePlaybackControl> enumerator = controls.GetEnumerator();
			while (enumerator.MoveNext())
			{
				PlayerVoicePlaybackControl current = enumerator.Current;
				if (!((Object)(object)current == (Object)null))
				{
					float num = PlayerVoiceInfo.AudibleRange(current);
					if (num > 0f)
					{
						return $"Current received-voice edge: approximately {num:0} metres.";
					}
				}
			}
			return "Effective distance appears after another player speaks.";
		}

		private void SetRange(float value, bool notify = false)
		{
			float num = Mathf.Clamp(value, 1f, 20f);
			Plugin.Instance.RangeMultiplier.Value = num;
			_rangeText = num.ToString("0.##", CultureInfo.InvariantCulture);
			ApplySettings();
			if (notify)
			{
				ShowToast($"VOICE RANGE  ×{num:0.##}", RangePresetDescription(num));
			}
		}

		private void SetTwoD(bool enabled, bool notify)
		{
			Plugin.Instance.TwoDVoice.Value = enabled;
			ApplySettings();
			if (notify)
			{
				ShowToast(enabled ? "2D VOICE" : "3D SPATIAL VOICE", enabled ? "Voices are centred with no distance fade." : "Direction and distance are restored.");
			}
		}

		private void CycleRange()
		{
			float value = Plugin.Instance.RangeMultiplier.Value;
			float value2 = RangePresets[0];
			float[] rangePresets = RangePresets;
			foreach (float num in rangePresets)
			{
				if (num > value + 0.01f)
				{
					value2 = num;
					break;
				}
			}
			SetRange(value2, notify: true);
		}

		private static string RangePresetDescription(float range)
		{
			if (range <= 1.01f)
			{
				return "Vanilla received-voice distance.";
			}
			if (range <= 2.01f)
			{
				return "A comfortable social boost.";
			}
			if (range <= 5.01f)
			{
				return "Wide-area conversation.";
			}
			if (range <= 10.01f)
			{
				return "Far-reaching conversation.";
			}
			return "Maximum received-voice distance.";
		}

		private void ShowToast(string title, string detail)
		{
			_toastTitle = title;
			_toastDetail = detail;
			_toastUntil = Time.unscaledTime + 2.6f;
		}

		private void ResetDefaults()
		{
			Plugin.Instance.RangeMultiplier.Value = 1f;
			Plugin.Instance.TwoDVoice.Value = false;
			Plugin.Instance.SpeakerIndicators.Value = true;
			Plugin.Instance.SpeakerNames.Value = true;
			Plugin.Instance.ActiveSpeakerRoster.Value = true;
			Plugin.Instance.SpeakerDistances.Value = true;
			Plugin.Instance.HudScale.Value = 1f;
			Plugin.Instance.TalkThreshold.Value = 0.004f;
			_rangeText = "1";
			ApplySettings();
			ShowToast("VOICE SETTINGS RESET", "Vanilla range, 3D audio, and the full speaker HUD.");
		}

		private void DrawToast()
		{
			//IL_0045: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(460f, (float)Screen.width - 32f);
			float num2 = 72f;
			float num3 = ((float)Screen.width - num) * 0.5f;
			float num4 = 26f;
			GUI.color = new Color(0.025f, 0.03f, 0.035f, 0.94f);
			GUI.DrawTexture(new Rect(num3, num4, num, num2), (Texture)(object)_panelTexture);
			GUI.color = Color.white;
			GUI.DrawTexture(new Rect(num3, num4, 5f, num2), (Texture)(object)_accentTexture);
			GUI.color = Color.white;
			GUI.Label(new Rect(num3 + 18f, num4 + 8f, num - 30f, 26f), _toastTitle, _toastTitleStyle);
			GUI.Label(new Rect(num3 + 18f, num4 + 34f, num - 30f, 25f), _toastDetail, _mutedLabelStyle);
		}

		private void ApplySettings()
		{
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			try
			{
				float value = (VoiceRangeScaler.Scale = Mathf.Clamp(Plugin.Instance.RangeMultiplier.Value, 1f, 20f));
				VoiceRangeScaler.Apply();
				List<PlayerVoicePlaybackControl> controls = PlayerVoicePlaybackControl.controls;
				if (controls != null)
				{
					Enumerator<PlayerVoicePlaybackControl> enumerator = controls.GetEnumerator();
					while (enumerator.MoveNext())
					{
						PlayerVoicePlaybackControl current = enumerator.Current;
						if ((Object)(object)current != (Object)null)
						{
							current.TwoDMode = Plugin.Instance.TwoDVoice.Value;
						}
					}
				}
				_status = ((VoiceRangeScaler.LastApplied == 0) ? "Waiting for remote players…" : $"Applied ×{value:0.##} to {VoiceRangeScaler.LastApplied} player(s).");
			}
			catch (Exception ex)
			{
				_status = "Could not apply voice settings; check the BepInEx log.";
				ManualLogSource trace = Plugin.Trace;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(32, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Applying voice settings failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				trace.LogError(val);
			}
		}

		private void SetVisible(bool visible)
		{
			//IL_003e: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			if (_visible == visible)
			{
				return;
			}
			_visible = visible;
			if (!Plugin.Instance.FreeCursor.Value)
			{
				return;
			}
			if (visible)
			{
				_previousLockState = Cursor.lockState;
				_previousCursorVisible = Cursor.visible;
				return;
			}
			Cursor.lockState = _previousLockState;
			Cursor.visible = _previousCursorVisible;
			SettingsMenu returnToSettingsMenu = _returnToSettingsMenu;
			_returnToSettingsMenu = null;
			if ((Object)(object)returnToSettingsMenu != (Object)null)
			{
				((Component)returnToSettingsMenu).gameObject.SetActive(true);
				returnToSettingsMenu.SetToAudio();
				NativeSettingsIntegration.Refresh();
			}
		}

		internal void ApplyImmediately()
		{
			ApplySettings();
		}

		internal void OpenFromNativeSettings(SettingsMenu settingsMenu)
		{
			_returnToSettingsMenu = settingsMenu;
			if (settingsMenu != null)
			{
				((Component)settingsMenu).gameObject.SetActive(false);
			}
			SetVisible(visible: true);
		}
	}
}