Decompiled source of QuickWheel v1.1.0

QuickWheel.dll

Decompiled 14 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ComputerysModdingUtilities;
using FishNet.Object;
using HeathenEngineering.DEMO;
using Microsoft.CodeAnalysis;
using ModMenu.Api;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: StraftatMod(true)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("QuickWheel")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Radial quick-chat wheel for STRAFTAT")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("neptune.straftat.quickwheel")]
[assembly: AssemblyTitle("QuickWheel")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace QuickWheel
{
	internal static class ModMenuBridge
	{
		public const string Guid = "kestrel.straftat.modmenu";

		private static Component pageMarker;

		public static bool PageOpen
		{
			get
			{
				if ((Object)(object)pageMarker != (Object)null)
				{
					return pageMarker.gameObject.activeInHierarchy;
				}
				return false;
			}
		}

		public static void Register()
		{
			ModMenuCustomisation.RegisterContentBuilder((Action<OptionListContext>)delegate(OptionListContext context)
			{
				pageMarker = (Component)(object)context.PrependTextBox("Turn on Show Wheel While Editing to preview the wheel here as you change settings.");
			});
		}
	}
	[BepInPlugin("neptune.straftat.quickwheel", "QuickWheel", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private const float PreviewAlpha = 0.45f;

		private const float PreviewSpinSpeed = 120f;

		private readonly List<string> slots = new List<string>();

		private readonly WheelRenderer wheel = new WheelRenderer();

		private bool wheelOpen;

		private Vector2 pointer;

		private int selected = -1;

		private float lastSentAt = -999f;

		private FirstPersonController owner;

		private bool trackOwner;

		private LobbyChatUILogic chatRef;

		private PauseManager pmRef;

		private readonly List<InputAction> lookDisabled = new List<InputAction>();

		private readonly List<InputAction> fireDisabled = new List<InputAction>();

		private bool fireRestorePending;

		private float previewUntil = -1f;

		private FileSystemWatcher configWatcher;

		private volatile bool configFileChanged;

		private float ignoreFileChangesUntil;

		private bool hasModMenu;

		private bool keyClashChecked;

		private string keyClash;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			((MonoBehaviour)this).useGUILayout = false;
			QuickWheelConfig.Bind(((BaseUnityPlugin)this).Config);
			((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged;
			WatchConfigFile();
			RebuildSlots();
			hasModMenu = Chainloader.PluginInfos.ContainsKey("kestrel.straftat.modmenu");
			if (hasModMenu)
			{
				RegisterWithModMenu();
			}
			Log.LogInfo((object)"QuickWheel loaded.");
		}

		private void OnDestroy()
		{
			configWatcher?.Dispose();
		}

		private void Update()
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			if (configFileChanged)
			{
				ReloadConfigFromDisk();
			}
			if (!keyClashChecked)
			{
				CheckKeyClash();
			}
			if (fireRestorePending)
			{
				TryRestoreFire();
			}
			if ((Object)(object)chatRef == (Object)null)
			{
				chatRef = (((Object)(object)LobbyChatUILogic.Instance != (Object)null) ? LobbyChatUILogic.Instance : Object.FindObjectOfType<LobbyChatUILogic>());
			}
			if ((Object)(object)pmRef == (Object)null)
			{
				pmRef = (((Object)(object)PauseManager.Instance != (Object)null) ? PauseManager.Instance : Object.FindObjectOfType<PauseManager>());
			}
			LobbyChatUILogic val = chatRef;
			PauseManager val2 = pmRef;
			bool num = (Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null && !val2.inMainMenu && !val2.pause && !val2.chatting;
			KeyboardShortcut value = QuickWheelConfig.OpenKey.Value;
			bool flag = QuickWheelConfig.Open.Value == OpenMode.Hold;
			if (!num || (wheelOpen && !OwnerAlive()))
			{
				if (wheelOpen)
				{
					Close();
				}
				else if (KeyDown(value))
				{
					Log.LogInfo((object)$"Wheel not opened: chat={(Object)(object)val != (Object)null} pauseManager={(Object)(object)val2 != (Object)null} mainMenu={val2?.inMainMenu} paused={val2?.pause} typing={val2?.chatting}");
				}
				return;
			}
			if (KeyDown(value))
			{
				if (!wheelOpen)
				{
					OpenWheel();
				}
				else if (!flag)
				{
					Close();
					return;
				}
			}
			if (!wheelOpen)
			{
				return;
			}
			if (flag && Input.GetKeyUp(((KeyboardShortcut)(ref value)).MainKey))
			{
				if (QuickWheelConfig.Send.Value == SendMode.Release)
				{
					SendSelected(val);
				}
				Close();
				return;
			}
			if (lookDisabled.Count > 0)
			{
				if ((Object)(object)owner != (Object)null)
				{
					owner.mouseInput = Vector2.zero;
				}
				else
				{
					FirstPersonController[] array = Object.FindObjectsOfType<FirstPersonController>();
					for (int i = 0; i < array.Length; i++)
					{
						array[i].mouseInput = Vector2.zero;
					}
				}
			}
			Mouse current = Mouse.current;
			if (current != null)
			{
				float value2 = QuickWheelConfig.SelectDistance.Value;
				pointer = Vector2.ClampMagnitude(pointer + ((InputControl<Vector2>)(object)((Pointer)current).delta).ReadValue(), value2 * 1.5f);
				selected = ((((Vector2)(ref pointer)).magnitude >= value2) ? SliceAt(pointer, slots.Count) : (-1));
				if (current.rightButton.wasPressedThisFrame)
				{
					Close();
				}
				else if (current.leftButton.wasPressedThisFrame && selected >= 0)
				{
					SendSelected(val);
					Close();
				}
			}
		}

		private void OnGUI()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Event.current.type != 7 || (!wheelOpen && (!hasModMenu || !ModMenuPageOpen() || (!QuickWheelConfig.ShowWhileEditing.Value && Time.unscaledTime > previewUntil))) || slots.Count == 0)
			{
				return;
			}
			float value = QuickWheelConfig.SelectDistance.Value;
			float value2 = QuickWheelConfig.WheelSize.Value;
			if (wheelOpen)
			{
				wheel.Draw(slots, selected, pointer, value, value2, 1f, null, null);
				return;
			}
			float num = Time.unscaledTime * 120f * (MathF.PI / 180f);
			Vector2 dir = new Vector2(Mathf.Sin(num), Mathf.Cos(num)) * value * 1.25f;
			object obj;
			if (keyClash != null)
			{
				KeyboardShortcut value3 = QuickWheelConfig.OpenKey.Value;
				obj = $"{((KeyboardShortcut)(ref value3)).MainKey} is also bound in-game to: {keyClash}";
			}
			else
			{
				obj = null;
			}
			string warning = (string)obj;
			wheel.Draw(slots, SliceAt(dir, slots.Count), dir, value, value2, 0.45f, $"select distance {value:0}", warning);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool ModMenuPageOpen()
		{
			return ModMenuBridge.PageOpen;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void RegisterWithModMenu()
		{
			ModMenuBridge.Register();
		}

		private void OnSettingChanged(object sender, SettingChangedEventArgs e)
		{
			RebuildSlots();
			if ((object)e.ChangedSetting == QuickWheelConfig.OpenKey)
			{
				keyClashChecked = false;
			}
			previewUntil = (((object)e.ChangedSetting == QuickWheelConfig.ShowWhileEditing) ? (-1f) : (Time.unscaledTime + QuickWheelConfig.PreviewDuration.Value));
			ignoreFileChangesUntil = Time.unscaledTime + 0.5f;
		}

		private void RebuildSlots()
		{
			if (wheelOpen)
			{
				return;
			}
			slots.Clear();
			int value = QuickWheelConfig.SlotCount.Value;
			ConfigEntry<string>[] phrases = QuickWheelConfig.Phrases;
			foreach (ConfigEntry<string> val in phrases)
			{
				if (slots.Count >= value)
				{
					break;
				}
				if (!string.IsNullOrWhiteSpace(val.Value))
				{
					slots.Add(val.Value.Trim());
				}
			}
			if (slots.Count > 0)
			{
				wheel.Prepare(slots.Count);
			}
		}

		private void WatchConfigFile()
		{
			try
			{
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				configWatcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath))
				{
					NotifyFilter = (NotifyFilters.Size | NotifyFilters.LastWrite),
					EnableRaisingEvents = true
				};
				configWatcher.Changed += delegate
				{
					configFileChanged = true;
				};
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not watch config file, live reload disabled: " + ex.Message));
			}
		}

		private void ReloadConfigFromDisk()
		{
			configFileChanged = false;
			if (Time.unscaledTime < ignoreFileChangesUntil)
			{
				return;
			}
			ignoreFileChangesUntil = Time.unscaledTime + 0.5f;
			try
			{
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch (IOException)
			{
				configFileChanged = true;
				ignoreFileChangesUntil = 0f;
			}
		}

		private void OpenWheel()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (slots.Count == 0)
			{
				Log.LogInfo((object)"Wheel not opened: no phrases set");
				return;
			}
			owner = FindLocalPlayer();
			trackOwner = (Object)(object)owner != (Object)null;
			previewUntil = -1f;
			pointer = Vector2.zero;
			selected = -1;
			wheelOpen = true;
			PlayerControls inputActions = InputManager.inputActions;
			if (inputActions != null)
			{
				PlayerActions player = inputActions.Player;
				if (QuickWheelConfig.FreezeAim.Value)
				{
					DisableActions(lookDisabled, ((PlayerActions)(ref player)).MouseX, ((PlayerActions)(ref player)).MouseY);
				}
				fireRestorePending = false;
				DisableActions(fireDisabled, ((PlayerActions)(ref player)).LeftClick, ((PlayerActions)(ref player)).RightClick, ((PlayerActions)(ref player)).FireHold);
			}
		}

		private void Close()
		{
			wheelOpen = false;
			selected = -1;
			RebuildSlots();
			if (!OwnerAlive())
			{
				lookDisabled.Clear();
				fireDisabled.Clear();
				return;
			}
			foreach (InputAction item in lookDisabled)
			{
				item.Enable();
			}
			lookDisabled.Clear();
			fireRestorePending = fireDisabled.Count > 0;
		}

		private void SendSelected(LobbyChatUILogic chat)
		{
			//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)
			if (selected >= 0 && selected < slots.Count && !(Time.time - lastSentAt < QuickWheelConfig.Cooldown.Value))
			{
				if (chat.inQuickMatch && (Object)(object)chat.QuickMatchScript != (Object)null)
				{
					chat.lobbyManager.Lobby = chat.QuickMatchScript.Lobby;
				}
				chat.SendChatMessage(slots[selected]);
				lastSentAt = Time.time;
			}
		}

		private void TryRestoreFire()
		{
			if (!OwnerAlive())
			{
				fireDisabled.Clear();
				fireRestorePending = false;
				return;
			}
			Mouse current = Mouse.current;
			if (current != null && (current.leftButton.isPressed || current.rightButton.isPressed))
			{
				return;
			}
			foreach (InputAction item in fireDisabled)
			{
				item.Enable();
			}
			fireDisabled.Clear();
			fireRestorePending = false;
		}

		private static void DisableActions(List<InputAction> into, params InputAction[] actions)
		{
			foreach (InputAction val in actions)
			{
				if (val != null && val.enabled && !into.Contains(val))
				{
					val.Disable();
					into.Add(val);
				}
			}
		}

		private bool OwnerAlive()
		{
			if (trackOwner)
			{
				if ((Object)(object)owner != (Object)null)
				{
					return ((Component)owner).gameObject.activeInHierarchy;
				}
				return false;
			}
			return true;
		}

		private static FirstPersonController FindLocalPlayer()
		{
			FirstPersonController[] array = Object.FindObjectsOfType<FirstPersonController>();
			foreach (FirstPersonController val in array)
			{
				if (((NetworkBehaviour)val).IsOwner)
				{
					return val;
				}
			}
			return null;
		}

		private void CheckKeyClash()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (InputManager.inputActions == null)
			{
				return;
			}
			keyClashChecked = true;
			keyClash = null;
			KeyboardShortcut value = QuickWheelConfig.OpenKey.Value;
			string text = KeyPath(((KeyboardShortcut)(ref value)).MainKey);
			if (text == null)
			{
				return;
			}
			List<string> list = new List<string>();
			PlayerActions player = InputManager.inputActions.Player;
			Enumerator<InputAction> enumerator = ((PlayerActions)(ref player)).Get().actions.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					InputAction current = enumerator.Current;
					if (current.name == "Any")
					{
						continue;
					}
					Enumerator<InputBinding> enumerator2 = current.bindings.GetEnumerator();
					try
					{
						while (enumerator2.MoveNext())
						{
							InputBinding current2 = enumerator2.Current;
							if (string.Equals(((InputBinding)(ref current2)).effectivePath, text, StringComparison.OrdinalIgnoreCase))
							{
								list.Add(current.name);
								break;
							}
						}
					}
					finally
					{
						((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			if (list.Count != 0)
			{
				keyClash = string.Join(", ", list);
				ManualLogSource log = Log;
				value = QuickWheelConfig.OpenKey.Value;
				log.LogWarning((object)$"Open key {((KeyboardShortcut)(ref value)).MainKey} is also bound in-game to: {keyClash}");
			}
		}

		private unsafe static string KeyPath(KeyCode key)
		{
			//IL_0000: 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_0020: Expected I4, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Invalid comparison between Unknown and I4
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Invalid comparison between Unknown and I4
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Invalid comparison between Unknown and I4
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected I4, but got Unknown
			switch (key - 323)
			{
			case 0:
				return "<Mouse>/leftButton";
			case 1:
				return "<Mouse>/rightButton";
			case 2:
				return "<Mouse>/middleButton";
			case 3:
				return "<Mouse>/backButton";
			case 4:
				return "<Mouse>/forwardButton";
			default:
				if ((int)key >= 97 && (int)key <= 122)
				{
					return "<Keyboard>/" + ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString().ToLowerInvariant();
				}
				if ((int)key >= 48 && (int)key <= 57)
				{
					return "<Keyboard>/" + (key - 48);
				}
				if ((int)key >= 282 && (int)key <= 293)
				{
					return "<Keyboard>/" + ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString().ToLowerInvariant();
				}
				return null;
			}
		}

		private static bool KeyDown(KeyboardShortcut key)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!Input.GetKeyDown(((KeyboardShortcut)(ref key)).MainKey))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref key)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			return true;
		}

		private static int SliceAt(Vector2 dir, int count)
		{
			//IL_0000: 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)
			float num = Mathf.Atan2(dir.x, dir.y) * 57.29578f;
			if (num < 0f)
			{
				num += 360f;
			}
			float num2 = 360f / (float)count;
			return Mathf.FloorToInt((num + num2 / 2f) / num2) % count;
		}
	}
	public enum OpenMode
	{
		Hold,
		Toggle
	}
	public enum SendMode
	{
		Click,
		Release
	}
	public static class QuickWheelConfig
	{
		public const int MaxSlots = 8;

		private const string EditingSection = "1. Editing";

		private const string PhrasesSection = "2. Phrases";

		private const string ControlsSection = "3. Controls";

		private const string DisplaySection = "4. Display";

		private const string ChatSection = "5. Chat";

		public static ConfigEntry<bool> ShowWhileEditing;

		public static ConfigEntry<KeyboardShortcut> OpenKey;

		public static ConfigEntry<OpenMode> Open;

		public static ConfigEntry<SendMode> Send;

		public static ConfigEntry<float> SelectDistance;

		public static ConfigEntry<float> WheelSize;

		public static ConfigEntry<int> SlotCount;

		public static ConfigEntry<float> PreviewDuration;

		public static ConfigEntry<float> Cooldown;

		public static ConfigEntry<bool> FreezeAim;

		public static ConfigEntry<string>[] Phrases = new ConfigEntry<string>[8];

		public static void Bind(ConfigFile config)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Expected O, but got Unknown
			ShowWhileEditing = config.Bind<bool>("1. Editing", "Show Wheel While Editing", false, "Show a faint preview of the wheel while this mod's page is open in Mod Menu, so you can see changes as you make them.");
			string[] array = new string[8] { "gg", "nice shot", "push!", "fall back", "I'm low", "they're low", "wait for me", "thanks" };
			for (int i = 0; i < 8; i++)
			{
				Phrases[i] = config.Bind<string>("2. Phrases", $"Slot {i + 1}", array[i], $"Phrase for wheel slot {i + 1} (slot 1 is at the top, then clockwise). Leave empty to remove the slot.");
			}
			OpenKey = config.Bind<KeyboardShortcut>("3. Controls", "Open Wheel", new KeyboardShortcut((KeyCode)326, Array.Empty<KeyCode>()), "Key or mouse button that opens the wheel. Mouse3/Mouse4 are the side buttons.");
			Open = config.Bind<OpenMode>("3. Controls", "Open Mode", OpenMode.Hold, "Hold: wheel is open while the key is held. Toggle: press once to open, again to close.");
			Send = config.Bind<SendMode>("3. Controls", "Send Mode", SendMode.Click, "Click: left click sends the highlighted phrase. Release: letting go of the key sends it (Hold mode only).");
			FreezeAim = config.Bind<bool>("3. Controls", "Freeze Aim", true, "Stop the camera turning while the wheel is open so mouse movement only picks a slice.");
			SelectDistance = config.Bind<float>("3. Controls", "Select Distance", 40f, new ConfigDescription("How far (in mouse counts, roughly pixels) you need to move to highlight a slice. Shown as the inner circle on the wheel.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 300f), Array.Empty<object>()));
			SlotCount = config.Bind<int>("4. Display", "Slot Count", 8, new ConfigDescription("How many slices the wheel has. Uses the first N phrases.", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[5] { 2, 3, 4, 6, 8 }), Array.Empty<object>()));
			WheelSize = config.Bind<float>("4. Display", "Wheel Size", 360f, new ConfigDescription("Wheel diameter in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(200f, 800f), Array.Empty<object>()));
			PreviewDuration = config.Bind<float>("4. Display", "Settings Preview", 3f, new ConfigDescription("Seconds a faint preview flashes on this mod's Mod Menu page after changing a setting (when Show Wheel While Editing is off). 0 turns it off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			Cooldown = config.Bind<float>("5. Chat", "Cooldown", 0.75f, new ConfigDescription("Minimum seconds between sent messages.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
		}
	}
	public class WheelRenderer
	{
		private const int TexSize = 256;

		private const float InnerRadius = 0.38f;

		private const float LabelRadius = 0.69f;

		private static readonly Color32 BaseColor = new Color32((byte)15, (byte)15, (byte)20, (byte)170);

		private static readonly Color32 LineColor = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)60);

		private static readonly Color32 HighlightColor = new Color32(byte.MaxValue, (byte)190, (byte)40, (byte)200);

		private static readonly Color32 ThresholdColor = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)110);

		private int builtFor = -1;

		private Texture2D ringTex;

		private Texture2D circleTex;

		private Texture2D[] highlightTex;

		private GUIStyle labelStyle;

		private GUIStyle labelSelectedStyle;

		private GUIStyle centerStyle;

		private GUIStyle warningStyle;

		public void Prepare(int count)
		{
			if (builtFor != count)
			{
				Build(count);
			}
			if ((Object)(object)circleTex == (Object)null)
			{
				circleTex = MakeCircle();
			}
		}

		public void Draw(List<string> slots, int selected, Vector2 pointer, float selectDistance, float size, float alpha, string info, string warning)
		{
			//IL_0026: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			int count = slots.Count;
			Prepare(count);
			if (labelStyle == null)
			{
				BuildStyles();
			}
			GUI.depth = -1000;
			Color color = GUI.color;
			GUI.color = new Color(1f, 1f, 1f, alpha);
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor((float)Screen.width / 2f, (float)Screen.height / 2f);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(val.x - size / 2f, val.y - size / 2f, size, size);
			GUI.DrawTexture(val2, (Texture)(object)ringTex);
			if (selected >= 0)
			{
				GUI.DrawTexture(val2, (Texture)(object)highlightTex[selected]);
			}
			float num = 360f / (float)count;
			for (int i = 0; i < count; i++)
			{
				float num2 = (float)i * num * (MathF.PI / 180f);
				Vector2 val3 = val + new Vector2(Mathf.Sin(num2), 0f - Mathf.Cos(num2)) * (size / 2f * 0.69f);
				DrawShadowed(new Rect(val3.x - 70f, val3.y - 20f, 140f, 40f), style: (i == selected) ? labelSelectedStyle : labelStyle, text: slots[i]);
			}
			float num3 = selectDistance * 2f;
			GUI.DrawTexture(new Rect(val.x - num3 / 2f, val.y - num3 / 2f, num3, num3), (Texture)(object)circleTex);
			Vector2 val4 = val + new Vector2(pointer.x, 0f - pointer.y);
			GUI.DrawTexture(new Rect(val4.x - 4f, val4.y - 4f, 8f, 8f), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(1f, 1f, 1f, alpha), 0f, 4f);
			DrawShadowed(text: (info != null) ? info : ((selected >= 0) ? ((QuickWheelConfig.Send.Value == SendMode.Release && QuickWheelConfig.Open.Value == OpenMode.Hold) ? "release" : "click") : "RMB cancel"), r: new Rect(val.x - 80f, val.y + selectDistance + 4f, 160f, 24f), style: centerStyle);
			if (warning != null)
			{
				GUI.color = Color.white;
				DrawShadowed(new Rect(val.x - 200f, val.y + size / 2f + 8f, 400f, 40f), warning, warningStyle);
			}
			GUI.color = color;
		}

		private static void DrawShadowed(Rect r, string text, GUIStyle style)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			Color textColor = style.normal.textColor;
			style.normal.textColor = new Color(0f, 0f, 0f, 0.8f);
			GUI.Label(new Rect(((Rect)(ref r)).x + 1f, ((Rect)(ref r)).y + 1f, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, style);
			style.normal.textColor = textColor;
			GUI.Label(r, text, style);
		}

		private void BuildStyles()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_003d: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_007a: 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_0090: 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_00a4: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			labelStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)4,
				fontSize = 16,
				fontStyle = (FontStyle)1,
				wordWrap = true
			};
			labelStyle.normal.textColor = Color.white;
			labelSelectedStyle = new GUIStyle(labelStyle)
			{
				fontSize = 19
			};
			labelSelectedStyle.normal.textColor = new Color(0.1f, 0.08f, 0.02f);
			centerStyle = new GUIStyle(labelStyle)
			{
				fontSize = 12,
				fontStyle = (FontStyle)0
			};
			centerStyle.normal.textColor = new Color(1f, 1f, 1f, 0.6f);
			warningStyle = new GUIStyle(labelStyle)
			{
				fontSize = 14
			};
			warningStyle.normal.textColor = new Color(1f, 0.5f, 0.38f);
		}

		private void Build(int count)
		{
			Destroy();
			builtFor = count;
			ringTex = MakeTexture(count, -1);
			highlightTex = (Texture2D[])(object)new Texture2D[count];
			for (int i = 0; i < count; i++)
			{
				highlightTex[i] = MakeTexture(count, i);
			}
		}

		private void Destroy()
		{
			if ((Object)(object)ringTex != (Object)null)
			{
				Object.Destroy((Object)(object)ringTex);
			}
			if (highlightTex == null)
			{
				return;
			}
			Texture2D[] array = highlightTex;
			foreach (Texture2D val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		private static Texture2D MakeTexture(int count, int slice)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(256, 256, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[65536];
			float num = 128f;
			float num2 = 360f / (float)count;
			for (int i = 0; i < 256; i++)
			{
				for (int j = 0; j < 256; j++)
				{
					float num3 = ((float)j + 0.5f - num) / num;
					float num4 = ((float)i + 0.5f - num) / num;
					float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4);
					if (num5 > 1f || num5 < 0.38f)
					{
						continue;
					}
					float num6 = Mathf.Atan2(num3, num4) * 57.29578f;
					if (num6 < 0f)
					{
						num6 += 360f;
					}
					float num7 = Mathf.Repeat(num6 + num2 / 2f, num2);
					int num8 = Mathf.FloorToInt((num6 + num2 / 2f) / num2) % count;
					float num9 = Mathf.Clamp01(Mathf.Min(1f - num5, num5 - 0.38f) * num);
					Color32 val2;
					if (slice < 0)
					{
						float num10 = Mathf.Min(num7, num2 - num7) * (MathF.PI / 180f) * num5 * num;
						val2 = ((count > 1 && num10 < 1f) ? LineColor : BaseColor);
					}
					else
					{
						if (num8 != slice)
						{
							continue;
						}
						val2 = HighlightColor;
					}
					val2.a = (byte)((float)(int)val2.a * num9);
					array[i * 256 + j] = val2;
				}
			}
			val.SetPixels32(array);
			val.Apply();
			return val;
		}

		private static Texture2D MakeCircle()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(256, 256, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[65536];
			float num = 128f;
			for (int i = 0; i < 256; i++)
			{
				for (int j = 0; j < 256; j++)
				{
					float num2 = (float)j + 0.5f - num;
					float num3 = (float)i + 0.5f - num;
					float num4 = Mathf.Abs(Mathf.Sqrt(num2 * num2 + num3 * num3) - (num - 3f));
					if (!(num4 > 2f))
					{
						Color32 thresholdColor = ThresholdColor;
						thresholdColor.a = (byte)((float)(int)thresholdColor.a * Mathf.Clamp01(2f - num4));
						array[i * 256 + j] = thresholdColor;
					}
				}
			}
			val.SetPixels32(array);
			val.Apply();
			return val;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}