Decompiled source of Valheim Too Many Emotes v1.0.0

plugins/Valheim_TooManyEmotes.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Events;
using UnityEngine.Playables;
using UnityEngine.Rendering;
using UnityEngine.UI;
using Valheim.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TooManyEmotes
{
	public class Emote
	{
		public string Name;

		public AnimationClip Clip;

		public AnimationClip LoopClip;

		public bool IsPose;

		public string GroupName = "";

		public int Layer = -1;

		public bool RandomInGroup;

		public string VariantName = "";

		public List<Emote> Group;

		public bool Loops
		{
			get
			{
				if (!((Motion)Clip).isLooping)
				{
					return (Object)(object)LoopClip != (Object)null;
				}
				return true;
			}
		}

		public override string ToString()
		{
			return Name;
		}
	}
	public class EmoteEntry
	{
		public enum Kinds
		{
			Single,
			Random,
			Band
		}

		public string Key;

		public Kinds Kind;

		public List<Emote> Emotes = new List<Emote>();

		public string Label => Translations.EmoteLabel(Key);
	}
	public static class EmoteBrowser
	{
		private enum Tab
		{
			Favorites,
			All,
			Vanilla,
			Tme
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__Close;

			public static UnityAction <1>__Stop;
		}

		private const float Width = 560f;

		private const float Height = 680f;

		private const float RowHeight = 30f;

		private static GameObject panel;

		private static InputField search;

		private static RectTransform content;

		private static Text countText;

		private static readonly Dictionary<Tab, Button> tabButtons = new Dictionary<Tab, Button>();

		private static Tab tab = Tab.All;

		private static string builtLanguage;

		private static readonly CompareInfo Compare = CultureInfo.InvariantCulture.CompareInfo;

		public static bool IsOpen
		{
			get
			{
				if ((Object)(object)panel != (Object)null)
				{
					return panel.activeSelf;
				}
				return false;
			}
		}

		internal static List<MenuItem> Shown { get; private set; } = new List<MenuItem>();

		public static void Toggle()
		{
			if (IsOpen)
			{
				Close();
			}
			else
			{
				Open();
			}
		}

		public static void Open()
		{
			if ((Object)(object)GUIManager.CustomGUIFront == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			string selectedLanguage = Localization.instance.GetSelectedLanguage();
			if ((Object)(object)panel == (Object)null || builtLanguage != selectedLanguage)
			{
				if ((Object)(object)panel != (Object)null)
				{
					Object.Destroy((Object)(object)panel);
				}
				Build();
				builtLanguage = selectedLanguage;
			}
			panel.SetActive(true);
			GUIManager.BlockInput(true);
			if (tab == Tab.Favorites && Favorites.Keys.Count == 0)
			{
				tab = Tab.All;
			}
			Refresh();
			search.ActivateInputField();
		}

		public static void Close()
		{
			if (IsOpen)
			{
				panel.SetActive(false);
				GUIManager.BlockInput(false);
			}
		}

		private static void Build()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Expected O, but got Unknown
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Expected O, but got Unknown
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_040b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			//IL_049b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a6: Expected O, but got Unknown
			GUIManager instance = GUIManager.Instance;
			panel = instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 560f, 680f, true);
			((Object)panel).name = "TooManyEmotesBrowser";
			instance.CreateText(Translations.Ui("browser_title"), panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -32f), instance.AveriaSerifBold, 28, instance.ValheimOrange, true, Color.black, 440f, 40f, false).GetComponent<Text>().alignment = (TextAnchor)4;
			ButtonClickedEvent onClick = instance.CreateButton("X", panel.transform, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-38f, -34f), 40f, 40f).GetComponent<Button>().onClick;
			object obj = <>O.<0>__Close;
			if (obj == null)
			{
				UnityAction val = Close;
				<>O.<0>__Close = val;
				obj = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			search = instance.CreateInputField(panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -80f), (ContentType)0, Translations.Ui("search"), 18, 500f, 34f).GetComponent<InputField>();
			((UnityEvent<string>)(object)search.onValueChanged).AddListener((UnityAction<string>)delegate
			{
				Refresh();
			});
			float num = 125f;
			(Tab, string)[] array = new(Tab, string)[4]
			{
				(Tab.Favorites, "favorites"),
				(Tab.All, "all"),
				(Tab.Vanilla, "vanilla"),
				(Tab.Tme, "category")
			};
			tabButtons.Clear();
			for (int num2 = 0; num2 < array.Length; num2++)
			{
				(Tab, string) tuple = array[num2];
				Tab which = tuple.Item1;
				string item = tuple.Item2;
				GameObject obj2 = instance.CreateButton(Translations.Ui(item), panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(-250f + num * ((float)num2 + 0.5f), -124f), num - 6f, 36f);
				Text componentInChildren = obj2.GetComponentInChildren<Text>();
				componentInChildren.resizeTextForBestFit = true;
				componentInChildren.resizeTextMinSize = 10;
				componentInChildren.resizeTextMaxSize = 16;
				Button component = obj2.GetComponent<Button>();
				((UnityEvent)component.onClick).AddListener((UnityAction)delegate
				{
					tab = which;
					Refresh();
				});
				tabButtons[which] = component;
			}
			GameObject obj3 = instance.CreateScrollView(panel.transform, false, true, 8f, 4f, instance.ValheimScrollbarHandleColorBlock, new Color(0f, 0f, 0f, 0.4f), 500f, 430f);
			RectTransform val2 = (RectTransform)obj3.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.anchoredPosition = new Vector2(0f, -14f);
			content = obj3.GetComponentInChildren<ScrollRect>().content;
			VerticalLayoutGroup component2 = ((Component)content).GetComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component2).spacing = 2f;
			((LayoutGroup)component2).padding = new RectOffset(4, 4, 4, 4);
			countText = instance.CreateText("", panel.transform, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(110f, 34f), instance.AveriaSerif, 16, Color.white, true, Color.black, 180f, 30f, false).GetComponent<Text>();
			ButtonClickedEvent onClick2 = instance.CreateButton(Translations.Ui("stop"), panel.transform, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(-110f, 34f), 160f, 36f).GetComponent<Button>().onClick;
			object obj4 = <>O.<1>__Stop;
			if (obj4 == null)
			{
				UnityAction val4 = EmotePlayer.Stop;
				<>O.<1>__Stop = val4;
				obj4 = (object)val4;
			}
			((UnityEvent)onClick2).AddListener((UnityAction)obj4);
			panel.SetActive(false);
		}

		private static List<MenuItem> ItemsOf(Tab which)
		{
			return which switch
			{
				Tab.Favorites => MenuCatalog.FavoriteItems, 
				Tab.Vanilla => MenuCatalog.Vanilla, 
				Tab.Tme => MenuCatalog.TmeWithParts, 
				_ => MenuCatalog.All, 
			};
		}

		private static bool Matches(MenuItem item, string filter)
		{
			if (filter.Length != 0)
			{
				return Compare.IndexOf(item.Label, filter, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) >= 0;
			}
			return true;
		}

		private static void Refresh()
		{
			if ((Object)(object)panel == (Object)null)
			{
				return;
			}
			foreach (KeyValuePair<Tab, Button> tabButton in tabButtons)
			{
				((Selectable)tabButton.Value).interactable = tabButton.Key != tab;
			}
			string filter = search.text.Trim();
			Shown = (from i in ItemsOf(tab)
				where Matches(i, filter)
				select i).ToList();
			for (int num = ((Transform)content).childCount - 1; num >= 0; num--)
			{
				Object.Destroy((Object)(object)((Component)((Transform)content).GetChild(num)).gameObject);
			}
			foreach (MenuItem item in Shown)
			{
				AddRow(item);
			}
			countText.text = Translations.Ui("count", Shown.Count);
			if (tab == Tab.Favorites && Shown.Count == 0 && filter.Length == 0)
			{
				AddMessage(Translations.Ui("no_favorites"));
			}
		}

		private static void AddRow(MenuItem item)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0055: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Expected O, but got Unknown
			GUIManager instance = GUIManager.Instance;
			GameObject val = new GameObject("Row", new Type[2]
			{
				typeof(RectTransform),
				typeof(LayoutElement)
			});
			val.transform.SetParent((Transform)(object)content, false);
			((RectTransform)val.transform).sizeDelta = new Vector2(470f, 30f);
			val.GetComponent<LayoutElement>().preferredHeight = 30f;
			GameObject obj = instance.CreateToggle(val.transform, 24f, 24f);
			RectTransform val2 = (RectTransform)obj.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.anchoredPosition = new Vector2(16f, 0f);
			Toggle component = obj.GetComponent<Toggle>();
			component.isOn = Favorites.Contains(item.Key);
			((UnityEvent<bool>)(object)component.onValueChanged).AddListener((UnityAction<bool>)delegate(bool on)
			{
				if (on != Favorites.Contains(item.Key))
				{
					Favorites.Toggle(item.Key);
				}
			});
			GameObject obj2 = instance.CreateButton(item.Label, val.transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(250f, 0f), 420f, 28f);
			Text componentInChildren = obj2.GetComponentInChildren<Text>();
			componentInChildren.alignment = (TextAnchor)3;
			componentInChildren.fontSize = 16;
			((Graphic)componentInChildren).rectTransform.offsetMin = new Vector2(10f, 0f);
			((UnityEvent)obj2.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				item.Play();
			});
		}

		private static void AddMessage(string text)
		{
			//IL_000d: 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_0017: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			GUIManager instance = GUIManager.Instance;
			GameObject obj = instance.CreateText(text, (Transform)(object)content, Vector2.zero, Vector2.one, Vector2.zero, instance.AveriaSerif, 16, Color.white, true, Color.black, 460f, 80f, false);
			obj.AddComponent<LayoutElement>().preferredHeight = 80f;
			obj.GetComponent<Text>().alignment = (TextAnchor)4;
		}

		internal static void Update()
		{
			if (IsOpen)
			{
				if ((Object)(object)Player.m_localPlayer == (Object)null)
				{
					Close();
				}
				else if (ZInput.GetKeyDown((KeyCode)27, false))
				{
					Close();
				}
			}
		}

		internal static void Destroy()
		{
			if ((Object)(object)panel != (Object)null)
			{
				Object.Destroy((Object)(object)panel);
				panel = null;
			}
		}
	}
	[HarmonyPatch(typeof(Menu), "Update")]
	internal static class MenuEscapePatch
	{
		private static bool Prefix()
		{
			return !EmoteBrowser.IsOpen;
		}
	}
	public class EmoteController : MonoBehaviour
	{
		private const float FadeInTime = 0.25f;

		private const float FadeOutTime = 0.3f;

		private const float MaxAirTime = 0.4f;

		private static readonly int ZdoEmote = StringExtensionMethods.GetStableHashCode("TME_emote");

		private static readonly int ZdoId = StringExtensionMethods.GetStableHashCode("TME_id");

		private static readonly int ZdoStart = StringExtensionMethods.GetStableHashCode("TME_start");

		private static readonly FieldRef<Character, Animator> AnimatorRef = AccessTools.FieldRefAccess<Character, Animator>("m_animator");

		private static readonly FieldRef<Character, ZNetView> NViewRef = AccessTools.FieldRefAccess<Character, ZNetView>("m_nview");

		private static readonly FieldRef<Humanoid, ItemData> HiddenRightRef = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_hiddenRightItem");

		private static readonly FieldRef<Humanoid, ItemData> HiddenLeftRef = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_hiddenLeftItem");

		private static readonly MethodInfo ShowHandItemsMethod = AccessTools.Method(typeof(Humanoid), "ShowHandItems", (Type[])null, (Type[])null);

		private static readonly MethodInfo VanillaStopEmoteMethod = AccessTools.Method(typeof(Player), "StopEmote", (Type[])null, (Type[])null);

		private static readonly MethodInfo SetCrouchMethod = AccessTools.Method(typeof(Player), "SetCrouch", (Type[])null, (Type[])null);

		internal static readonly Dictionary<Animator, EmoteController> Active = new Dictionary<Animator, EmoteController>();

		internal static readonly Dictionary<Player, EmoteController> Emoting = new Dictionary<Player, EmoteController>();

		private Player player;

		private Animator animator;

		private ZNetView nview;

		private PlayableGraph graph;

		private AnimationPlayableOutput output;

		private AnimationMixerPlayable mixer;

		private AnimationClipPlayable introPlayable;

		private AnimationClipPlayable loopPlayable;

		private bool inLoopPhase;

		private float weight;

		private float targetWeight;

		private bool savedApplyRootMotion;

		private int appliedId = -1;

		private float airTime;

		internal bool stoppingVanilla;

		private bool inSession;

		private bool hidItems;

		private float inactiveSince = -1f;

		public Emote Current { get; private set; }

		public bool IsEmoting
		{
			get
			{
				if (Current != null)
				{
					return targetWeight > 0f;
				}
				return false;
			}
		}

		public float Weight
		{
			get
			{
				if (!((PlayableGraph)(ref graph)).IsValid())
				{
					return 0f;
				}
				return weight;
			}
		}

		public Animator Animator => animator;

		public Player Player => player;

		private bool IsOwner
		{
			get
			{
				if ((Object)(object)nview != (Object)null && nview.IsValid())
				{
					return nview.IsOwner();
				}
				return false;
			}
		}

		private ZDO Zdo
		{
			get
			{
				if (!((Object)(object)nview != (Object)null) || !nview.IsValid())
				{
					return null;
				}
				return nview.GetZDO();
			}
		}

		public float CurrentTime
		{
			get
			{
				//IL_003b: 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)
				if (((PlayableGraph)(ref graph)).IsValid() && Current != null)
				{
					if (!inLoopPhase)
					{
						return (float)PlayableExtensions.GetTime<AnimationClipPlayable>(introPlayable);
					}
					return Current.Clip.length + (float)PlayableExtensions.GetTime<AnimationClipPlayable>(loopPlayable);
				}
				return 0f;
			}
		}

		internal bool InSession => inSession;

		internal bool HidItems => hidItems;

		public static EmoteController For(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			EmoteController emoteController = ((Component)player).GetComponent<EmoteController>();
			if ((Object)(object)emoteController == (Object)null)
			{
				emoteController = ((Component)player).gameObject.AddComponent<EmoteController>();
			}
			return emoteController;
		}

		internal static float WeightOf(Animator animator)
		{
			if (!((Object)(object)animator != (Object)null) || !Active.TryGetValue(animator, out var value) || !((Object)(object)value != (Object)null))
			{
				return 0f;
			}
			return value.Weight;
		}

		private void Awake()
		{
			player = ((Component)this).GetComponent<Player>();
			animator = AnimatorRef.Invoke((Character)(object)player);
			nview = NViewRef.Invoke((Character)(object)player);
		}

		internal static void Trace(string message)
		{
			if (Plugin.Verbose)
			{
				Plugin.Log.LogMessage((object)("[EmoteController] " + message));
			}
		}

		public string DescribeGraph()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if (!((PlayableGraph)(ref graph)).IsValid())
			{
				return "graph=none";
			}
			string text = $"graph playing={((PlayableGraph)(ref graph)).IsPlaying()} outputWeight={PlayableOutputExtensions.GetWeight<AnimationPlayableOutput>(output):0.00} weight={weight:0.00} target={targetWeight:0.00} ";
			object arg = PlayableExtensions.GetTime<AnimationClipPlayable>(introPlayable);
			Emote current = Current;
			return text + $"intro t={arg:0.00}/{((current != null) ? new float?(current.Clip.length) : ((float?)null)):0.00} loopPhase={inLoopPhase}";
		}

		public string DescribeState()
		{
			return $"dead={((Character)player).IsDead()} ground={((Character)player).IsOnGround()} swim={((Character)player).IsSwimming()} attached={((Character)player).IsAttached()} " + $"ship={((Character)player).IsAttachedToShip()} attack={((Character)player).InAttack()} dodge={((Character)player).InDodge()} stagger={((Character)player).IsStaggering()} " + $"canMove={((Character)player).CanMove()} bow={((Character)player).IsDrawingBow()} teleport={((Character)player).IsTeleporting()} bed={((Character)player).InBed()} " + "right=" + (((Humanoid)player).RightItem?.m_shared.m_name ?? "none") + " left=" + (((Humanoid)player).LeftItem?.m_shared.m_name ?? "none");
		}

		public bool CanEmote()
		{
			bool flag = IsOwner && Zdo.GetString(ZDOVars.s_emote, "") != "";
			if ((Object)(object)player != (Object)null && (Object)(object)animator != (Object)null && animator.isHuman && IsOwner && !((Character)player).IsDead() && ((Character)player).IsOnGround() && !((Character)player).IsSwimming() && (((Character)player).CanMove() || flag) && !((Character)player).InAttack() && !((Character)player).InDodge() && !((Character)player).IsDrawingBow() && !((Character)player).IsStaggering() && !((Character)player).IsAttached() && !((Character)player).IsAttachedToShip() && !((Character)player).IsTeleporting())
			{
				return !((Character)player).InBed();
			}
			return false;
		}

		public bool RequestPlay(Emote emote, float startTime = 0f)
		{
			if (emote == null)
			{
				return false;
			}
			if (!CanEmote())
			{
				Trace("cannot emote " + emote.Name + ": " + DescribeState());
				return false;
			}
			BeginSession();
			stoppingVanilla = true;
			try
			{
				VanillaStopEmoteMethod.Invoke(player, null);
			}
			finally
			{
				stoppingVanilla = false;
			}
			SetCrouchMethod.Invoke(player, new object[1] { false });
			ZDO zdo = Zdo;
			zdo.Set(ZdoEmote, emote.Name);
			zdo.Set(ZdoStart, ZNet.instance.GetTime().Ticks - (long)(startTime * 10000000f));
			zdo.Set(ZdoId, zdo.GetInt(ZdoId, 0) + 1, false);
			SyncFromZdo();
			return true;
		}

		public void RequestStop()
		{
			ZDO zdo = Zdo;
			if (zdo != null && IsOwner && !(zdo.GetString(ZdoEmote, "") == ""))
			{
				zdo.Set(ZdoEmote, "");
				zdo.Set(ZdoId, zdo.GetInt(ZdoId, 0) + 1, false);
				SyncFromZdo();
			}
		}

		private string InterruptReason()
		{
			if (((Character)player).IsDead())
			{
				return "dead";
			}
			if (((Character)player).IsSwimming())
			{
				return "swimming";
			}
			if (((Character)player).IsAttached() || ((Character)player).IsAttachedToShip())
			{
				return "attached";
			}
			if (((Character)player).InAttack())
			{
				return "attack";
			}
			if (((Character)player).InDodge())
			{
				return "dodge";
			}
			if (((Character)player).IsStaggering())
			{
				return "stagger";
			}
			if (((Character)player).IsTeleporting())
			{
				return "teleport";
			}
			if (((Character)player).InBed())
			{
				return "bed";
			}
			if (((Character)player).IsDrawingBow())
			{
				return "bow";
			}
			if (airTime > 0.4f)
			{
				return "airborne";
			}
			return null;
		}

		private void BeginSession()
		{
			if (!inSession)
			{
				Trace("session begins: " + DescribeState());
				inSession = true;
				inactiveSince = -1f;
				hidItems = false;
				if (Plugin.HideHandItems.Value && (((Humanoid)player).RightItem != null || ((Humanoid)player).LeftItem != null))
				{
					hidItems = ((Humanoid)player).HideHandItems(false, true);
					Trace($"hand items hidden: {hidItems}");
				}
			}
		}

		private void UpdateSession()
		{
			if (!inSession)
			{
				return;
			}
			if (IsEmoting)
			{
				inactiveSince = -1f;
				return;
			}
			if (inactiveSince < 0f)
			{
				inactiveSince = Time.time;
			}
			if (Time.time - inactiveSince < 0.3f)
			{
				return;
			}
			inSession = false;
			Trace($"session ends (hid items: {hidItems})");
			if (hidItems && !((Character)player).IsDead())
			{
				hidItems = false;
				if (((Humanoid)player).RightItem == null && ((Humanoid)player).LeftItem == null && (HiddenRightRef.Invoke((Humanoid)(object)player) != null || HiddenLeftRef.Invoke((Humanoid)(object)player) != null) && (!((Character)player).IsSwimming() || ((Character)player).IsOnGround()))
				{
					Trace("showing hand items again");
					ShowHandItemsMethod.Invoke(player, new object[2] { false, true });
				}
			}
		}

		private void SyncFromZdo()
		{
			ZDO zdo = Zdo;
			if (zdo == null || !EmoteLibrary.Ready)
			{
				return;
			}
			int num = zdo.GetInt(ZdoId, 0);
			if (num == appliedId)
			{
				return;
			}
			appliedId = num;
			string text = zdo.GetString(ZdoEmote, "");
			if (string.IsNullOrEmpty(text) || !EmoteLibrary.ByName.TryGetValue(text, out var value))
			{
				if (!string.IsNullOrEmpty(text))
				{
					Trace("unknown emote '" + text + "' on " + player.GetPlayerName());
				}
				FadeOut();
			}
			else
			{
				float num2 = Mathf.Max(0f, (float)((double)(ZNet.instance.GetTime().Ticks - zdo.GetLong(ZdoStart, 0L)) / 10000000.0));
				if (!value.Loops && !value.IsPose && num2 >= value.Clip.length)
				{
					FadeOut();
				}
				else
				{
					Begin(value, num2);
				}
			}
		}

		private void Begin(Emote emote, float startTime)
		{
			//IL_004a: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//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_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: 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_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: 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_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			bool num = ((PlayableGraph)(ref graph)).IsValid();
			if (num)
			{
				((PlayableGraph)(ref graph)).Destroy();
			}
			else
			{
				savedApplyRootMotion = animator.applyRootMotion;
			}
			graph = PlayableGraph.Create("TooManyEmotes_" + player.GetPlayerID());
			((PlayableGraph)(ref graph)).SetTimeUpdateMode((DirectorUpdateMode)1);
			output = AnimationPlayableOutput.Create(graph, "Emote", animator);
			mixer = AnimationMixerPlayable.Create(graph, 2);
			introPlayable = AnimationClipPlayable.Create(graph, emote.Clip);
			((PlayableGraph)(ref graph)).Connect<AnimationClipPlayable, AnimationMixerPlayable>(introPlayable, 0, mixer, 0);
			PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(mixer, 0, 1f);
			if ((Object)(object)emote.LoopClip != (Object)null)
			{
				loopPlayable = AnimationClipPlayable.Create(graph, emote.LoopClip);
				((PlayableGraph)(ref graph)).Connect<AnimationClipPlayable, AnimationMixerPlayable>(loopPlayable, 0, mixer, 1);
				PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(mixer, 1, 0f);
				PlayableExtensions.Pause<AnimationClipPlayable>(loopPlayable);
			}
			PlayableOutputExtensions.SetSourcePlayable<AnimationPlayableOutput, AnimationMixerPlayable>(output, mixer);
			animator.applyRootMotion = false;
			Current = emote;
			inLoopPhase = false;
			if (startTime > 0f)
			{
				if (PlayableExtensions.IsValid<AnimationClipPlayable>(loopPlayable) && startTime >= emote.Clip.length)
				{
					PlayableExtensions.SetTime<AnimationClipPlayable>(introPlayable, (double)emote.Clip.length);
					PlayableExtensions.Pause<AnimationClipPlayable>(introPlayable);
					PlayableExtensions.SetTime<AnimationClipPlayable>(loopPlayable, (double)((startTime - emote.Clip.length) % Mathf.Max(emote.LoopClip.length, 0.01f)));
					PlayableExtensions.Play<AnimationClipPlayable>(loopPlayable);
					PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(mixer, 0, 0f);
					PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(mixer, 1, 1f);
					inLoopPhase = true;
				}
				else if (emote.IsPose && !((Motion)emote.Clip).isLooping)
				{
					PlayableExtensions.SetTime<AnimationClipPlayable>(introPlayable, (double)Mathf.Min(startTime, emote.Clip.length));
				}
				else
				{
					PlayableExtensions.SetTime<AnimationClipPlayable>(introPlayable, (double)(((Motion)emote.Clip).isLooping ? (startTime % Mathf.Max(emote.Clip.length, 0.01f)) : startTime));
				}
			}
			if (!num)
			{
				weight = 0f;
			}
			targetWeight = 1f;
			PlayableOutputExtensions.SetWeight<AnimationPlayableOutput>(output, weight);
			((PlayableGraph)(ref graph)).Play();
			Active[animator] = this;
			Emoting[player] = this;
			Trace($"started {emote.Name} on {player.GetPlayerName()} at {startTime:0.00} s: {DescribeGraph()}");
		}

		private void FadeOut()
		{
			targetWeight = 0f;
			Emoting.Remove(player);
		}

		internal void SnapWeight()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (((PlayableGraph)(ref graph)).IsValid())
			{
				weight = targetWeight;
				PlayableOutputExtensions.SetWeight<AnimationPlayableOutput>(output, weight);
			}
		}

		private void Update()
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			SyncFromZdo();
			if (IsOwner)
			{
				airTime = (((Character)player).IsOnGround() ? 0f : (airTime + Time.deltaTime));
				if (IsEmoting)
				{
					string text = InterruptReason();
					if (text != null)
					{
						Trace("interrupted (" + text + "): " + DescribeState());
						RequestStop();
					}
				}
				UpdateSession();
			}
			if (((PlayableGraph)(ref graph)).IsValid())
			{
				if (targetWeight > 0f)
				{
					AdvancePhase();
				}
				float num = ((targetWeight > weight) ? 0.25f : 0.3f);
				weight = Mathf.MoveTowards(weight, targetWeight, Time.deltaTime / num);
				PlayableOutputExtensions.SetWeight<AnimationPlayableOutput>(output, weight);
				if (weight <= 0f && targetWeight <= 0f)
				{
					Teardown();
				}
			}
		}

		private void LateUpdate()
		{
			if (((PlayableGraph)(ref graph)).IsValid() && Current != null && weight > 0f)
			{
				FingerCurl.Apply(animator, inLoopPhase ? Current.LoopClip : Current.Clip, weight);
			}
		}

		private void AdvancePhase()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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)
			if (inLoopPhase || PlayableExtensions.GetTime<AnimationClipPlayable>(introPlayable) < (double)Current.Clip.length)
			{
				return;
			}
			if (PlayableExtensions.IsValid<AnimationClipPlayable>(loopPlayable))
			{
				PlayableExtensions.SetTime<AnimationClipPlayable>(loopPlayable, 0.0);
				PlayableExtensions.Play<AnimationClipPlayable>(loopPlayable);
				PlayableExtensions.Pause<AnimationClipPlayable>(introPlayable);
				PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(mixer, 0, 0f);
				PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(mixer, 1, 1f);
				inLoopPhase = true;
			}
			else if (Current.IsPose && !((Motion)Current.Clip).isLooping)
			{
				PlayableExtensions.Pause<AnimationClipPlayable>(introPlayable);
			}
			else if (!((Motion)Current.Clip).isLooping)
			{
				if (IsOwner)
				{
					RequestStop();
				}
				else
				{
					FadeOut();
				}
			}
		}

		private void Teardown()
		{
			if (((PlayableGraph)(ref graph)).IsValid())
			{
				Trace("teardown " + Current?.Name);
				((PlayableGraph)(ref graph)).Destroy();
				if ((Object)(object)animator != (Object)null)
				{
					animator.applyRootMotion = savedApplyRootMotion;
				}
			}
			if ((Object)(object)animator != (Object)null)
			{
				Active.Remove(animator);
			}
			Emoting.Remove(player);
			Current = null;
			inLoopPhase = false;
			weight = 0f;
			targetWeight = 0f;
		}

		private void OnDisable()
		{
			Teardown();
		}

		private void OnDestroy()
		{
			Teardown();
		}
	}
	public static class EmoteLibrary
	{
		private static readonly string[] BundleNames = new string[6] { "emotes_complementary", "emotes_0", "emotes_1", "emotes_2", "emotes_3", "emotes_special" };

		public static readonly List<Emote> All = new List<Emote>();

		public static readonly Dictionary<string, Emote> ByName = new Dictionary<string, Emote>();

		public static readonly List<EmoteEntry> Entries = new List<EmoteEntry>();

		public static readonly Dictionary<string, EmoteEntry> EntryByKey = new Dictionary<string, EmoteEntry>();

		internal static readonly List<AssetBundle> Bundles = new List<AssetBundle>();

		public static bool Ready { get; private set; }

		internal static IEnumerable<string> BundleFileNames => BundleNames;

		public static IEnumerator Load(string assetsDir)
		{
			Stopwatch timer = Stopwatch.StartNew();
			Dictionary<string, AnimationClip> clips = new Dictionary<string, AnimationClip>();
			string[] bundleNames = BundleNames;
			foreach (string path in bundleNames)
			{
				string path2 = Path.Combine(assetsDir, path);
				AssetBundleCreateRequest bundleRequest = AssetBundle.LoadFromFileAsync(path2);
				yield return bundleRequest;
				AssetBundle assetBundle = bundleRequest.assetBundle;
				if ((Object)(object)assetBundle == (Object)null)
				{
					Plugin.Log.LogError((object)("Failed to load emote bundle " + path2));
					continue;
				}
				Bundles.Add(assetBundle);
				AssetBundleRequest assetsRequest = assetBundle.LoadAllAssetsAsync<AnimationClip>();
				yield return assetsRequest;
				foreach (AnimationClip item in assetsRequest.allAssets.OfType<AnimationClip>())
				{
					if (!clips.ContainsKey(((Object)item).name))
					{
						clips.Add(((Object)item).name, item);
					}
				}
			}
			Build(clips);
			Ready = true;
			MenuCatalog.Invalidate();
			Plugin.Log.LogMessage((object)$"Emote library loaded in {timer.ElapsedMilliseconds} ms (in the background)");
		}

		private static void Build(Dictionary<string, AnimationClip> clips)
		{
			Dictionary<string, List<Emote>> dictionary = new Dictionary<string, List<Emote>>();
			foreach (AnimationClip item in clips.Values.OrderBy<AnimationClip, string>((AnimationClip c) => ((Object)c).name, StringComparer.Ordinal))
			{
				if (((Object)item).name.EndsWith("_loop") && clips.ContainsKey(((Object)item).name.Substring(0, ((Object)item).name.Length - 5) + "_start"))
				{
					continue;
				}
				Emote emote = Parse(item, clips);
				if (emote == null || ByName.ContainsKey(emote.Name))
				{
					continue;
				}
				All.Add(emote);
				ByName.Add(emote.Name, emote);
				if (emote.GroupName.Length != 0)
				{
					if (!dictionary.TryGetValue(emote.GroupName, out var value))
					{
						dictionary.Add(emote.GroupName, value = new List<Emote>());
					}
					value.Add(emote);
					emote.Group = value;
				}
			}
			foreach (Emote item2 in All.Where((Emote e) => e.GroupName.Length == 0))
			{
				AddEntry(new EmoteEntry
				{
					Key = item2.Name,
					Kind = EmoteEntry.Kinds.Single,
					Emotes = { item2 }
				});
			}
			foreach (KeyValuePair<string, List<Emote>> item3 in dictionary)
			{
				List<Emote> value2 = item3.Value;
				bool flag = value2.Any((Emote e) => e.Layer >= 0);
				if (flag)
				{
					value2.Sort((Emote a, Emote b) => a.Layer.CompareTo(b.Layer));
				}
				AddEntry(new EmoteEntry
				{
					Key = item3.Key,
					Kind = ((!flag) ? EmoteEntry.Kinds.Random : EmoteEntry.Kinds.Band),
					Emotes = value2.ToList()
				});
			}
			Plugin.Log.LogMessage((object)$"Loaded {clips.Count} clips: {All.Count} emotes, {Entries.Count} menu entries, {dictionary.Count} groups.");
		}

		private static void AddEntry(EmoteEntry entry)
		{
			Entries.Add(entry);
			EntryByKey[entry.Key] = entry;
		}

		private static Emote Parse(AnimationClip clip, Dictionary<string, AnimationClip> clips)
		{
			Emote emote = new Emote
			{
				Clip = clip
			};
			string text = ((Object)clip).name;
			if (text.EndsWith("_start") && clips.TryGetValue(text.Substring(0, text.Length - 6) + "_loop", out var value))
			{
				emote.LoopClip = value;
				text = text.Substring(0, text.Length - 6);
			}
			else if (text.EndsWith("_pose"))
			{
				emote.IsPose = true;
				text = text.Substring(0, text.Length - 5);
			}
			if (text.Contains("."))
			{
				string[] array = text.Split('.');
				if (array.Length == 2 && array[1].Length == 0)
				{
					emote.Name = text;
					return emote;
				}
				if (array.Length > 3 || array[0].Length == 0)
				{
					Plugin.Log.LogWarning((object)("Unexpected emote name format: " + ((Object)clip).name));
					return null;
				}
				emote.GroupName = array[0];
				emote.VariantName = array[^1];
				if (array.Length == 3)
				{
					string text2 = array[1].ToLowerInvariant();
					if (text2.StartsWith("layer_") && int.TryParse(text2.Substring(6), out var result))
					{
						emote.Layer = result;
					}
					else if (text2 == "random")
					{
						emote.RandomInGroup = true;
					}
				}
				if (emote.GroupName.EndsWith("_pose"))
				{
					emote.IsPose = true;
				}
			}
			emote.Name = text;
			return emote;
		}
	}
	public static class EmotePreview
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static CameraCallback <0>__OnPreCull;

			public static CameraCallback <1>__OnPostRender;
		}

		private const int TextureSize = 512;

		private const float RestartPause = 0.6f;

		private const float PoseHold = 1.5f;

		private static readonly Vector3 Origin = new Vector3(0f, 6000f, 0f);

		private static readonly Color Background = new Color(0.075f, 0.065f, 0.055f, 1f);

		private static readonly FieldRef<Character, Animator> AnimatorRef = AccessTools.FieldRefAccess<Character, Animator>("m_animator");

		private static readonly string[] HandItemFields = new string[2] { "m_rightItemInstance", "m_leftItemInstance" };

		private static RenderTexture texture;

		private static Camera camera;

		private static readonly List<Light> lights = new List<Light>();

		private static int layer = -1;

		private static GameObject holder;

		private static Animator animator;

		private static PlayableGraph graph;

		private static AnimationMixerPlayable mixer;

		private static AnimationClipPlayable intro;

		private static AnimationClipPlayable loop;

		private static MenuItem shown;

		private static Emote emote;

		private static string vanillaName;

		private static bool vanillaOneShot;

		private static float startedAt;

		private static float endedAt = -1f;

		private static readonly int EmoteTag = Animator.StringToHash("emote");

		private static AmbientMode savedAmbientMode;

		private static Color savedAmbient;

		private static bool savedFog;

		private static bool overridden;

		public static Texture Texture => (Texture)(object)texture;

		public static bool Active => (Object)(object)holder != (Object)null;

		internal static Animator PreviewAnimator => animator;

		internal static Camera PreviewCamera => camera;

		private static void Trace(string message)
		{
			if (Plugin.Verbose)
			{
				Plugin.Log.LogMessage((object)("[EmotePreview] " + message));
			}
		}

		public static bool Begin(Player player)
		{
			End();
			Animator val = (((Object)(object)player != (Object)null) ? AnimatorRef.Invoke((Character)(object)player) : null);
			if ((Object)(object)val == (Object)null || !val.isHuman)
			{
				return false;
			}
			if (!EnsureStage())
			{
				return false;
			}
			try
			{
				BuildCopy(player, val);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Emote preview unavailable: " + ex));
				End();
				return false;
			}
			((Behaviour)camera).enabled = true;
			Trace($"model copied: {holder.GetComponentsInChildren<Renderer>().Length} renderers");
			return true;
		}

		public static void End()
		{
			StopAll();
			if ((Object)(object)holder != (Object)null)
			{
				Object.Destroy((Object)(object)holder);
			}
			holder = null;
			animator = null;
			shown = null;
			if ((Object)(object)camera != (Object)null)
			{
				((Behaviour)camera).enabled = false;
			}
		}

		public static void Show(MenuItem item)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			if (item == shown || (Object)(object)animator == (Object)null)
			{
				return;
			}
			Trace("show " + (item?.Key ?? "nothing"));
			shown = item;
			StopAll();
			if (!(item is TmeItem tmeItem))
			{
				if (!(item is TmePartItem tmePartItem))
				{
					if (item is VanillaItem vanillaItem)
					{
						Emote attributeOfType = Utils.GetAttributeOfType<Emote>((Enum)(object)vanillaItem.Emote);
						vanillaName = ((object)vanillaItem.Emote/*cast due to .constrained prefix*/).ToString().ToLower();
						vanillaOneShot = attributeOfType?.OneShot ?? true;
						PlayVanilla();
					}
				}
				else
				{
					PlayTme(tmePartItem.Part);
				}
			}
			else
			{
				PlayTme(tmeItem.Entry.Emotes[0]);
			}
		}

		public static void Update()
		{
			if (!((Object)(object)animator == (Object)null))
			{
				if (emote != null && ((PlayableGraph)(ref graph)).IsValid())
				{
					UpdateTme();
				}
				else if (vanillaName != null)
				{
					UpdateVanilla();
				}
			}
		}

		public static void LateUpdate()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)animator == (Object)null) && emote != null && ((PlayableGraph)(ref graph)).IsValid())
			{
				bool flag = PlayableExtensions.IsValid<AnimationClipPlayable>(loop) && PlayableExtensions.GetInputWeight<AnimationMixerPlayable>(mixer, 1) > 0f;
				FingerCurl.Apply(animator, flag ? emote.LoopClip : emote.Clip, 1f);
			}
		}

		private static void PlayTme(Emote which)
		{
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_005e: 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_0070: 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_00d5: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			emote = which;
			graph = PlayableGraph.Create("TooManyEmotes_Preview");
			((PlayableGraph)(ref graph)).SetTimeUpdateMode((DirectorUpdateMode)2);
			AnimationPlayableOutput val = AnimationPlayableOutput.Create(graph, "Preview", animator);
			mixer = AnimationMixerPlayable.Create(graph, 2);
			intro = AnimationClipPlayable.Create(graph, which.Clip);
			((PlayableGraph)(ref graph)).Connect<AnimationClipPlayable, AnimationMixerPlayable>(intro, 0, mixer, 0);
			PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(mixer, 0, 1f);
			if ((Object)(object)which.LoopClip != (Object)null)
			{
				loop = AnimationClipPlayable.Create(graph, which.LoopClip);
				((PlayableGraph)(ref graph)).Connect<AnimationClipPlayable, AnimationMixerPlayable>(loop, 0, mixer, 1);
				PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(mixer, 1, 0f);
				PlayableExtensions.Pause<AnimationClipPlayable>(loop);
			}
			PlayableOutputExtensions.SetSourcePlayable<AnimationPlayableOutput, AnimationMixerPlayable>(val, mixer);
			PlayableOutputExtensions.SetWeight<AnimationPlayableOutput>(val, 1f);
			((PlayableGraph)(ref graph)).Play();
			endedAt = -1f;
			startedAt = Time.unscaledTime;
		}

		private static void UpdateTme()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_00a6: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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)
			if (PlayableExtensions.IsValid<AnimationClipPlayable>(loop) && PlayableExtensions.GetInputWeight<AnimationMixerPlayable>(mixer, 1) > 0f)
			{
				return;
			}
			if (endedAt >= 0f)
			{
				if (Time.unscaledTime - endedAt >= (emote.IsPose ? 1.5f : 0.6f))
				{
					PlayableExtensions.SetTime<AnimationClipPlayable>(intro, 0.0);
					PlayableExtensions.Play<AnimationClipPlayable>(intro);
					endedAt = -1f;
				}
			}
			else if (!((Motion)emote.Clip).isLooping && !(PlayableExtensions.GetTime<AnimationClipPlayable>(intro) < (double)emote.Clip.length))
			{
				if (PlayableExtensions.IsValid<AnimationClipPlayable>(loop))
				{
					PlayableExtensions.SetTime<AnimationClipPlayable>(loop, 0.0);
					PlayableExtensions.Play<AnimationClipPlayable>(loop);
					PlayableExtensions.Pause<AnimationClipPlayable>(intro);
					PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(mixer, 0, 0f);
					PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(mixer, 1, 1f);
				}
				else
				{
					PlayableExtensions.SetTime<AnimationClipPlayable>(intro, (double)emote.Clip.length);
					PlayableExtensions.Pause<AnimationClipPlayable>(intro);
					endedAt = Time.unscaledTime;
				}
			}
		}

		private static void PlayVanilla()
		{
			animator.ResetTrigger("emote_stop");
			if (vanillaOneShot)
			{
				animator.SetTrigger("emote_" + vanillaName);
			}
			else
			{
				animator.SetBool("emote_" + vanillaName, true);
			}
			startedAt = Time.unscaledTime;
			endedAt = -1f;
		}

		private static void UpdateVanilla()
		{
			//IL_0020: 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)
			if (vanillaOneShot && !(Time.unscaledTime - startedAt < 0.5f))
			{
				AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
				if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).tagHash == EmoteTag || animator.IsInTransition(0))
				{
					endedAt = -1f;
				}
				else if (endedAt < 0f)
				{
					endedAt = Time.unscaledTime;
				}
				else if (Time.unscaledTime - endedAt >= 0.6f)
				{
					PlayVanilla();
				}
			}
		}

		private static void StopAll()
		{
			if (((PlayableGraph)(ref graph)).IsValid())
			{
				((PlayableGraph)(ref graph)).Destroy();
			}
			emote = null;
			if ((Object)(object)animator != (Object)null && vanillaName != null)
			{
				if (!vanillaOneShot)
				{
					animator.SetBool("emote_" + vanillaName, false);
				}
				animator.ResetTrigger("emote_" + vanillaName);
				animator.SetTrigger("emote_stop");
			}
			vanillaName = null;
			endedAt = -1f;
		}

		private static bool EnsureStage()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: 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_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: 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_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: 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_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Expected O, but got Unknown
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Expected O, but got Unknown
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Expected O, but got Unknown
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Expected O, but got Unknown
			if ((Object)(object)camera != (Object)null)
			{
				ExcludeLayerFromGame();
				return true;
			}
			int num = 31;
			while (num >= 8 && layer < 0)
			{
				if (string.IsNullOrEmpty(LayerMask.LayerToName(num)))
				{
					layer = num;
				}
				num--;
			}
			if (layer < 0)
			{
				Plugin.Log.LogWarning((object)"Emote preview unavailable: no free layer");
				return false;
			}
			Camera mainCamera = Utils.GetMainCamera();
			if ((Object)(object)mainCamera == (Object)null)
			{
				return false;
			}
			texture = new RenderTexture(512, 512, 24, (RenderTextureFormat)0)
			{
				name = "TooManyEmotes_Preview"
			};
			GameObject val = new GameObject("TooManyEmotes_PreviewStage");
			Object.DontDestroyOnLoad((Object)(object)val);
			GameObject val2 = new GameObject("Camera");
			val2.transform.SetParent(val.transform, false);
			camera = val2.AddComponent<Camera>();
			camera.CopyFrom(mainCamera);
			((Behaviour)camera).enabled = false;
			camera.clearFlags = (CameraClearFlags)2;
			camera.backgroundColor = Background;
			camera.cullingMask = 1 << layer;
			camera.fieldOfView = 30f;
			camera.nearClipPlane = 0.1f;
			camera.farClipPlane = 30f;
			camera.useOcclusionCulling = false;
			camera.depth = -50f;
			camera.targetTexture = texture;
			Vector3 val3 = Origin + Vector3.up * 0.88f;
			val2.transform.position = val3 + new Vector3(1.7f, 0.35f, 5.1f);
			val2.transform.LookAt(val3);
			AddLight(val, "Key", new Color(1f, 0.93f, 0.82f), 1.15f, new Vector3(35f, 200f, 0f));
			AddLight(val, "Fill", new Color(0.65f, 0.75f, 1f), 0.45f, new Vector3(10f, 120f, 0f));
			AddLight(val, "Rim", new Color(1f, 0.8f, 0.55f), 0.6f, new Vector3(20f, 20f, 0f));
			CameraCallback onPreCull = Camera.onPreCull;
			object obj = <>O.<0>__OnPreCull;
			if (obj == null)
			{
				CameraCallback val4 = OnPreCull;
				<>O.<0>__OnPreCull = val4;
				obj = (object)val4;
			}
			Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)onPreCull, (Delegate?)obj);
			CameraCallback onPostRender = Camera.onPostRender;
			object obj2 = <>O.<1>__OnPostRender;
			if (obj2 == null)
			{
				CameraCallback val5 = OnPostRender;
				<>O.<1>__OnPostRender = val5;
				obj2 = (object)val5;
			}
			Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)onPostRender, (Delegate?)obj2);
			ExcludeLayerFromGame();
			Trace($"stage: layer {layer}, path {camera.actualRenderingPath}, hdr {camera.allowHDR}");
			return true;
		}

		private static void AddLight(GameObject parent, string name, Color color, float intensity, Vector3 euler)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent.transform, false);
			val.transform.rotation = Quaternion.Euler(euler);
			Light val2 = val.AddComponent<Light>();
			val2.type = (LightType)1;
			val2.color = color;
			val2.intensity = intensity;
			val2.shadows = (LightShadows)0;
			val2.cullingMask = 1 << layer;
			lights.Add(val2);
		}

		private static void ExcludeLayerFromGame()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Invalid comparison between Unknown and I4
			int num = ~(1 << layer);
			Camera[] allCameras = Camera.allCameras;
			foreach (Camera val in allCameras)
			{
				if ((Object)(object)val != (Object)(object)camera)
				{
					val.cullingMask &= num;
				}
			}
			Light[] array = Object.FindObjectsByType<Light>((FindObjectsSortMode)0);
			foreach (Light val2 in array)
			{
				if ((int)val2.type == 1 && !lights.Contains(val2))
				{
					val2.cullingMask &= num;
				}
			}
		}

		private static void OnPreCull(Camera cam)
		{
			//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_0025: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)cam != (Object)(object)camera) && !overridden)
			{
				overridden = true;
				savedAmbientMode = RenderSettings.ambientMode;
				savedAmbient = RenderSettings.ambientLight;
				savedFog = RenderSettings.fog;
				RenderSettings.ambientMode = (AmbientMode)3;
				RenderSettings.ambientLight = new Color(0.42f, 0.4f, 0.38f);
				RenderSettings.fog = false;
			}
		}

		private static void OnPostRender(Camera cam)
		{
			//IL_001b: 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)
			if (!((Object)(object)cam != (Object)(object)camera) && overridden)
			{
				overridden = false;
				RenderSettings.ambientMode = savedAmbientMode;
				RenderSettings.ambientLight = savedAmbient;
				RenderSettings.fog = savedFog;
			}
		}

		private static void BuildCopy(Player player, Animator source)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_009f: Expected O, but got Unknown
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			holder = new GameObject("TooManyEmotes_PreviewModel");
			holder.SetActive(false);
			holder.transform.position = Origin;
			GameObject gameObject = ((Component)source).gameObject;
			GameObject val = Object.Instantiate<GameObject>(gameObject, holder.transform, false);
			((Object)val).name = "Visual";
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = gameObject.transform.localScale;
			Renderer[] componentsInChildren = gameObject.GetComponentsInChildren<Renderer>(true);
			Renderer[] componentsInChildren2 = val.GetComponentsInChildren<Renderer>(true);
			MaterialPropertyBlock val2 = new MaterialPropertyBlock();
			for (int i = 0; i < componentsInChildren.Length && i < componentsInChildren2.Length; i++)
			{
				if (componentsInChildren[i].HasPropertyBlock())
				{
					componentsInChildren[i].GetPropertyBlock(val2);
					componentsInChildren2[i].SetPropertyBlock(val2);
				}
			}
			foreach (SkinnedMeshRenderer item in componentsInChildren2.OfType<SkinnedMeshRenderer>())
			{
				item.updateWhenOffscreen = true;
			}
			VisEquipment component = ((Component)player).GetComponent<VisEquipment>();
			string[] handItemFields = HandItemFields;
			foreach (string text in handItemFields)
			{
				GameObject val3 = (GameObject)(((Object)(object)component != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
				string text2 = (((Object)(object)val3 != (Object)null) ? PathFrom(gameObject.transform, val3.transform) : null);
				Transform val4 = ((text2 != null) ? val.transform.Find(text2) : null);
				if ((Object)(object)val4 != (Object)null)
				{
					((Component)val4).gameObject.SetActive(false);
				}
			}
			Strip<MonoBehaviour>(val);
			Strip<Joint>(val);
			Strip<Cloth>(val);
			Strip<Collider>(val);
			Strip<Rigidbody>(val);
			Strip<AudioSource>(val);
			Strip<Light>(val);
			Transform[] componentsInChildren3 = val.GetComponentsInChildren<Transform>(true);
			for (int j = 0; j < componentsInChildren3.Length; j++)
			{
				((Component)componentsInChildren3[j]).gameObject.layer = layer;
			}
			animator = val.GetComponent<Animator>();
			animator.cullingMode = (AnimatorCullingMode)0;
			animator.applyRootMotion = false;
			animator.updateMode = (AnimatorUpdateMode)2;
			animator.fireEvents = false;
			holder.SetActive(true);
			animator.SetBool("wakeup", false);
			for (int k = 0; k < animator.layerCount && k < source.layerCount; k++)
			{
				AnimatorStateInfo currentAnimatorStateInfo = source.GetCurrentAnimatorStateInfo(k);
				animator.Play(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash, k, ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime);
			}
			animator.Update(0f);
		}

		private static void Strip<T>(GameObject root) where T : Component
		{
			for (int i = 0; i < 3; i++)
			{
				T[] componentsInChildren = root.GetComponentsInChildren<T>(true);
				if (componentsInChildren.Length == 0)
				{
					break;
				}
				T[] array = componentsInChildren;
				for (int j = 0; j < array.Length; j++)
				{
					Object.DestroyImmediate((Object)(object)array[j]);
				}
			}
		}

		private static string PathFrom(Transform root, Transform child)
		{
			List<string> list = new List<string>();
			Transform val = child;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			if (!child.IsChildOf(root))
			{
				return null;
			}
			list.Reverse();
			return string.Join("/", list);
		}
	}
	public class EmoteWheel : MonoBehaviour
	{
		public enum Tab
		{
			Favorites,
			All,
			Vanilla,
			Tme
		}

		private class Control
		{
			public RectTransform Rect;

			public TextMeshProUGUI Text;

			public Action OnClick;
		}

		private const float InnerRatio = 0.5f;

		private const float TapTime = 0.25f;

		private const float StickDeadZone = 0.5f;

		private static readonly (Tab tab, string key)[] Tabs = new(Tab, string)[4]
		{
			(Tab.Favorites, "favorites"),
			(Tab.All, "all"),
			(Tab.Vanilla, "vanilla"),
			(Tab.Tme, "category")
		};

		private static readonly Color Orange = new Color(1f, 0.64f, 0.25f);

		private static readonly Color LabelColor = new Color(0.9f, 0.87f, 0.8f);

		private static readonly Color FavoriteColor = new Color(1f, 0.8f, 0.35f);

		private static readonly Color DimColor = new Color(0.62f, 0.6f, 0.56f);

		internal static ConfigEntry<KeyboardShortcut> OpenKey;

		internal static ConfigEntry<KeyboardShortcut> FavoriteKey;

		internal static ConfigEntry<KeyboardShortcut> BrowserKey;

		internal static ConfigEntry<int> SlotsPerPage;

		internal static ConfigEntry<bool> ShowPreview;

		private static EmoteWheel instance;

		private static Tab lastTab = Tab.Tme;

		private static int closedFrame = -10;

		private static int chooserFrame = -1;

		private bool open;

		private bool sticky;

		private bool clickArmed;

		private bool padArmed;

		private float openedAt;

		private int openedFrame;

		private int slots;

		private float radius;

		internal static bool IgnorePointer;

		private static readonly MethodInfo StopEmoteMethod = AccessTools.Method(typeof(Player), "StopEmote", (Type[])null, (Type[])null);

		private readonly List<Control> controls = new List<Control>();

		private Control hoveredControl;

		private RectTransform root;

		private Image highlight;

		private Image previewDisk;

		private RawImage previewImage;

		private readonly List<TextMeshProUGUI> labels = new List<TextMeshProUGUI>();

		private readonly List<Image> icons = new List<Image>();

		private readonly List<(Tab tab, Control control)> tabControls = new List<(Tab, Control)>();

		private Control previousPage;

		private Control nextPage;

		private TextMeshProUGUI pageText;

		private TextMeshProUGUI nameText;

		private TextMeshProUGUI detailText;

		private TextMeshProUGUI hintText;

		private static Sprite ringSprite;

		private static Sprite diskSprite;

		private static Sprite edgeSprite;

		public static bool IsOpen
		{
			get
			{
				if ((Object)(object)instance != (Object)null)
				{
					return instance.open;
				}
				return false;
			}
		}

		internal static bool BlocksGame
		{
			get
			{
				if (!IsOpen)
				{
					return Time.frameCount <= closedFrame;
				}
				return true;
			}
		}

		internal static EmoteWheel Instance => instance;

		public Tab CurrentTab { get; private set; } = Tab.Tme;

		public int Page { get; private set; }

		public int Hovered { get; private set; } = -1;

		public List<MenuItem> Items { get; private set; } = new List<MenuItem>();

		public int PageCount => Math.Max(1, (Items.Count + slots - 1) / slots);

		public int Slots => slots;

		public MenuItem HoveredItem
		{
			get
			{
				if (Hovered < 0 || Page * slots + Hovered >= Items.Count)
				{
					return null;
				}
				return Items[Page * slots + Hovered];
			}
		}

		private Camera EventCamera
		{
			get
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				Canvas componentInParent = ((Component)this).GetComponentInParent<Canvas>();
				if (!((Object)(object)componentInParent == (Object)null) && (int)componentInParent.renderMode != 0)
				{
					return componentInParent.worldCamera;
				}
				return null;
			}
		}

		private float BandWidth => radius * 0.5f;

		private float MidRadius => radius * 1.5f / 2f;

		public static void Bind(ConfigFile config)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			OpenKey = config.Bind<KeyboardShortcut>("Wheel", "Open key", new KeyboardShortcut((KeyCode)96, Array.Empty<KeyCode>()), "Opens the Too Many Emotes wheel directly. Hold, aim, release to play; or tap, then click. The wheel is also in the game's emote wheel (Too Many Emotes).");
			FavoriteKey = config.Bind<KeyboardShortcut>("Wheel", "Favorite key", new KeyboardShortcut((KeyCode)102, Array.Empty<KeyCode>()), "Adds the emote under the cursor to the favorites, or removes it (gamepad: d-pad down).");
			BrowserKey = config.Bind<KeyboardShortcut>("Wheel", "Browser key", new KeyboardShortcut((KeyCode)98, Array.Empty<KeyCode>()), "Opens the emote browser (search field) from the wheel.");
			SlotsPerPage = config.Bind<int>("Wheel", "Emotes per page", 12, new ConfigDescription("Emotes shown around the wheel at once.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(6, 16), Array.Empty<object>()));
			ShowPreview = config.Bind<bool>("Wheel", "Preview", true, "Shows the emote under the cursor, played by a copy of your character, in the centre of the wheel.");
		}

		public static void Open(bool sticky)
		{
			//IL_005e: 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)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)GUIManager.CustomGUIFront == (Object)null)
			{
				return;
			}
			if (!EmoteLibrary.Ready)
			{
				((Character)localPlayer).Message((MessageType)2, Translations.Ui("loading"), 0, (Sprite)null, false);
				return;
			}
			if ((Object)(object)instance == (Object)null)
			{
				GameObject val = new GameObject("TooManyEmotes_Wheel", new Type[1] { typeof(RectTransform) });
				val.transform.SetParent(GUIManager.CustomGUIFront.transform, false);
				instance = val.AddComponent<EmoteWheel>();
			}
			instance.DoOpen(sticky);
		}

		public static void Close()
		{
			instance?.DoClose();
		}

		private void Awake()
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0026: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)((Component)this).transform;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			val.pivot = val2;
			Vector2 anchorMin = (val.anchorMax = val2);
			val.anchorMin = anchorMin;
			val.anchoredPosition = Vector2.zero;
			((Component)this).gameObject.SetActive(false);
		}

		private void DoOpen(bool sticky)
		{
			//IL_00eb: 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)
			if (!open)
			{
				slots = Mathf.Clamp(SlotsPerPage.Value, 6, 16);
				((Component)this).gameObject.SetActive(true);
				Build();
				open = true;
				this.sticky = sticky;
				clickArmed = (padArmed = false);
				openedAt = Time.unscaledTime;
				openedFrame = Time.frameCount;
				Hovered = -1;
				((Component)this).transform.SetAsLastSibling();
				bool active = ShowPreview.Value && EmotePreview.Begin(Player.m_localPlayer);
				((Component)previewDisk).gameObject.SetActive(active);
				previewImage.texture = EmotePreview.Texture;
				Tab tab = ((lastTab == Tab.Favorites && Favorites.Keys.Count == 0) ? Tab.Tme : lastTab);
				SetTab(tab, keepPage: true);
				if (!ZInput.IsGamepadActive())
				{
					ZInput.SetMousePosition(RectTransformUtility.WorldToScreenPoint(EventCamera, ((Component)this).transform.position));
				}
				GameCamera obj = GameCamera.instance;
				if (obj != null)
				{
					obj.UpdateMouseCapture();
				}
			}
		}

		private void DoClose()
		{
			if (open)
			{
				open = false;
				closedFrame = Time.frameCount;
				((Component)this).gameObject.SetActive(false);
				EmotePreview.End();
				GameCamera obj = GameCamera.instance;
				if (obj != null)
				{
					obj.UpdateMouseCapture();
				}
			}
		}

		private void OnDisable()
		{
			if (open)
			{
				open = false;
				EmotePreview.End();
			}
		}

		private static void OpenChooser()
		{
			Hud val = Hud.instance;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				RadialBase radialMenu = val.m_radialMenu;
				radialMenu.CanOpen = true;
				radialMenu.Open((IRadialConfig)(object)val.m_config, (IRadialConfig)null);
				if (radialMenu.Active)
				{
					radialMenu.HoverObject = null;
					radialMenu.Open((IRadialConfig)(object)RadialData.SO.EmoteGroupConfig, (IRadialConfig)null);
				}
			}
		}

		internal static void StaticUpdate()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (chooserFrame >= 0 && Time.frameCount > chooserFrame)
			{
				chooserFrame = -1;
				OpenChooser();
			}
			if (!IsOpen && !Hud.InRadial() && KeyDown(OpenKey.Value) && CanOpen())
			{
				Open(sticky: false);
			}
		}

		private static bool CanOpen()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead() && !((Character)localPlayer).InPlaceMode() && !Console.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible() && !Minimap.IsOpen() && !TextInput.IsVisible() && !StoreGui.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Hud.IsPieceSelectionVisible())
			{
				return !EmoteBrowser.IsOpen;
			}
			return false;
		}

		private static bool KeyDown(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, false))
			{
				return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((KeyCode k) => ZInput.GetKey(k, false));
			}
			return false;
		}

		private static bool KeyHeld(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && ZInput.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey, false))
			{
				return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((KeyCode k) => ZInput.GetKey(k, false));
			}
			return false;
		}

		private void Update()
		{
			//IL_0154: 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_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			if (!open)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting() || localPlayer.IsSleeping() || Menu.IsVisible() || Console.IsVisible() || InventoryGui.IsVisible() || Minimap.IsOpen() || ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()))
			{
				DoClose();
				return;
			}
			EmotePreview.Update();
			bool flag = Time.frameCount == openedFrame;
			if (ZInput.GetKeyDown((KeyCode)27, false) || ZInput.GetButtonDown("JoyRadialClose") || ZInput.GetButtonDown("JoyMenu") || ZInput.GetButtonDown("Chat") || ZInput.GetButtonDown("JoyChat") || ZInput.GetButtonDown("Map") || ZInput.GetButtonDown("JoyMap") || ZInput.GetButtonDown("Console") || (!flag && (ZInput.GetButtonDown("OpenEmote") || ZInput.GetButtonDown("OpenRadial") || ZInput.GetButtonDown("JoyRadial") || (sticky && KeyDown(OpenKey.Value)))))
			{
				DoClose();
				return;
			}
			if (ZInput.GetMouseButtonUp(1) || ZInput.GetButtonUp("JoyRadialBack"))
			{
				DoClose();
				chooserFrame = Time.frameCount;
				return;
			}
			if (KeyDown(BrowserKey.Value))
			{
				DoClose();
				EmoteBrowser.Open();
				return;
			}
			UpdateAim();
			int num = 0;
			float mouseScrollWheel = ZInput.GetMouseScrollWheel();
			if (mouseScrollWheel < 0f)
			{
				num++;
			}
			else if (mouseScrollWheel > 0f)
			{
				num--;
			}
			if (ZInput.GetButtonDown("JoyDPadRight"))
			{
				num++;
			}
			if (ZInput.GetButtonDown("JoyDPadLeft"))
			{
				num--;
			}
			if (num != 0)
			{
				SetPage(Page + num);
			}
			if (ZInput.GetKeyDown((KeyCode)9, false) || ZInput.GetButtonDown("JoyDPadUp"))
			{
				NextTab((!ZInput.GetKey((KeyCode)304, false)) ? 1 : (-1));
			}
			if (KeyDown(FavoriteKey.Value) || ZInput.GetButtonDown("JoyDPadDown") || ZInput.GetButtonDown("JoyRadialSecondaryInteract"))
			{
				ToggleFavorite();
			}
			if (ZInput.GetMouseButtonDown(0))
			{
				clickArmed = true;
			}
			if (ZInput.GetButtonDown("JoyRadialInteract"))
			{
				padArmed = true;
			}
			if (clickArmed && ZInput.GetMouseButtonUp(0))
			{
				clickArmed = false;
				if (!ClickControls())
				{
					Confirm();
				}
			}
			else if (padArmed && ZInput.GetButtonUp("JoyRadialInteract"))
			{
				Confirm();
			}
			else if (!sticky && !KeyHeld(OpenKey.Value))
			{
				if (Time.unscaledTime - openedAt < 0.25f && HoveredItem == null)
				{
					sticky = true;
				}
				else
				{
					Confirm();
				}
			}
		}

		private void LateUpdate()
		{
			if (open)
			{
				EmotePreview.LateUpdate();
			}
		}

		private void UpdateAim()
		{
			Control control = hoveredControl;
			AimAt();
			if (hoveredControl != control)
			{
				Refresh();
			}
		}

		private void AimAt()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			hoveredControl = null;
			if (IgnorePointer)
			{
				return;
			}
			if (ZInput.IsExclusiveGamepadActive())
			{
				Vector2 value = ZInput.GetValue<Vector2>("RadialStick");
				if (((Vector2)(ref value)).magnitude >= 0.5f)
				{
					SetAim(((Vector2)(ref value)).normalized);
				}
				return;
			}
			Vector2 pointer = Vector2.op_Implicit(ZInput.pointerPosition);
			hoveredControl = controls.FirstOrDefault((Control c) => ((Component)c.Rect).gameObject.activeInHierarchy && RectTransformUtility.RectangleContainsScreenPoint(c.Rect, pointer, EventCamera));
			Vector2 val = default(Vector2);
			if (hoveredControl != null)
			{
				SetHovered(-1);
			}
			else if (RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)((Component)this).transform, pointer, EventCamera, ref val))
			{
				SetAim(val / radius);
			}
		}

		public void SetAim(Vector2 aim)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			int hovered = ((((Vector2)(ref aim)).magnitude < 0.425f) ? (-1) : SlotAt(aim));
			SetHovered(hovered);
		}

		public void SetHovered(int slot)
		{
			if (slot >= 0 && Page * slots + slot >= Items.Count)
			{
				slot = -1;
			}
			if (slot != Hovered)
			{
				Hovered = slot;
				EmotePreview.Show(HoveredItem);
				Refresh();
			}
		}

		private int SlotAt(Vector2 aim)
		{
			//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(aim.x, aim.y) * 57.29578f;
			float num2 = 360f / (float)slots;
			return Mathf.FloorToInt(Mathf.Repeat(num + num2 / 2f, 360f) / num2) % slots;
		}

		private static float SlotAngle(int slot, int count)
		{
			return (float)slot * 360f / (float)count;
		}

		public void Confirm()
		{
			MenuItem hoveredItem = HoveredItem;
			DoClose();
			if (hoveredItem != null)
			{
				hoveredItem.Play();
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && ((Character)localPlayer).InEmote())
			{
				StopEmoteMethod.Invoke(localPlayer, null);
			}
		}

		public void ToggleFavorite()
		{
			MenuItem hoveredItem = HoveredItem;
			if (hoveredItem != null)
			{
				bool flag = Favorites.Toggle(hoveredItem.Key);
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)1, Translations.Ui(flag ? "fav_added" : "fav_removed", hoveredItem.Label), 0, (Sprite)null, false);
				}
				if (CurrentTab == Tab.Favorites)
				{
					SetTab(Tab.Favorites, keepPage: true);
				}
				Refresh();
			}
		}

		public void SetTab(Tab tab, bool keepPage = false)
		{
			int page = ((keepPage && tab == CurrentTab) ? Page : 0);
			CurrentTab = tab;
			lastTab = tab;
			Items = ItemsOf(tab);
			SetPage(page);
		}

		public void NextTab(int direction)
		{
			int num = Array.FindIndex(Tabs, ((Tab tab, string key) t) => t.tab == CurrentTab);
			SetTab(Tabs[(int)Mathf.Repeat((float)(num + direction), (float)Tabs.Length)].tab);
		}

		public void SetPage(int page)
		{
			int pageCount = PageCount;
			Page = (page % pageCount + pageCount) % pageCount;
			if (HoveredItem == null)
			{
				Hovered = -1;
			}
			EmotePreview.Show(HoveredItem);
			Refresh();
		}

		private static List<MenuItem> ItemsOf(Tab tab)
		{
			return tab switch
			{
				Tab.Favorites => MenuCatalog.FavoriteItems, 
				Tab.All => MenuCatalog.All, 
				Tab.Vanilla => MenuCatalog.Vanilla, 
				_ => MenuCatalog.TmeWithParts, 
			};
		}

		private bool ClickControls()
		{
			if (hoveredControl == null)
			{
				return false;
			}
			hoveredControl.OnClick();
			return true;
		}

		private void Refresh()
		{
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: 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)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: 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_0138: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0419: Unknown result type (might be due to invalid IL or missing references)
			//IL_041e: Unknown result type (might be due to invalid IL or missing references)
			if (labels.Count != slots)
			{
				return;
			}
			for (int i = 0; i < slots; i++)
			{
				int num = Page * slots + i;
				MenuItem menuItem = ((num < Items.Count) ? Items[num] : null);
				Sprite val = menuItem?.Icon;
				((Component)icons[i]).gameObject.SetActive((Object)(object)val != (Object)null);
				icons[i].sprite = val;
				((TMP_Text)labels[i]).text = menuItem?.Label ?? "";
				((TMP_Text)labels[i]).rectTransform.anchoredPosition = SlotCentre(i) - (Vector2)(((Object)(object)val != (Object)null) ? new Vector2(0f, BandWidth * 0.17f) : Vector2.zero);
				bool flag = menuItem != null && Favorites.Contains(menuItem.Key);
				((Graphic)labels[i]).color = ((i == Hovered) ? Color.white : (flag ? FavoriteColor : LabelColor));
				((TMP_Text)labels[i]).fontStyle = (FontStyles)((i == Hovered) ? 1 : 0);
			}
			((Behaviour)highlight).enabled = Hovered >= 0;
			if (Hovered >= 0)
			{
				((Transform)((Graphic)highlight).rectTransform).localRotation = Quaternion.Euler(0f, 0f, 180f / (float)slots - SlotAngle(Hovered, slots));
			}
			foreach (var tabControl in tabControls)
			{
				Tab item = tabControl.tab;
				Control item2 = tabControl.control;
				bool flag2 = item == CurrentTab;
				((Graphic)item2.Text).color = (flag2 ? Orange : ((item2 == hoveredControl) ? Color.white : DimColor));
				((TMP_Text)item2.Text).fontStyle = (FontStyles)(flag2 ? 1 : 0);
			}
			LayoutTabs();
			((TMP_Text)pageText).text = Translations.Ui("page", Page + 1, PageCount);
			((Component)previousPage.Rect).gameObject.SetActive(PageCount > 1);
			((Component)nextPage.Rect).gameObject.SetActive(PageCount > 1);
			((Graphic)previousPage.Text).color = ((previousPage == hoveredControl) ? Color.white : DimColor);
			((Graphic)nextPage.Text).color = ((nextPage == hoveredControl) ? Color.white : DimColor);
			MenuItem hoveredItem = HoveredItem;
			Player localPlayer = Player.m_localPlayer;
			if (hoveredItem != null)
			{
				((TMP_Text)nameText).text = hoveredItem.Label;
				((TMP_Text)detailText).text = (Favorites.Contains(hoveredItem.Key) ? Translations.Ui("favorite") : "");
			}
			else
			{
				((TMP_Text)nameText).text = (((Object)(object)localPlayer != (Object)null && ((Character)localPlayer).InEmote()) ? Translations.Ui("stop") : ((Items.Count != 0) ? "" : ((CurrentTab == Tab.Favorites) ? Translations.Ui("no_favorites_short") : Translations.Ui("nothing"))));
				((TMP_Text)detailText).text = "";
			}
			((TMP_Text)hintText).text = (ZInput.IsGamepadActive() ? Translations.Ui("hint_pad") : Translations.Ui("hint_mouse", ((object)FavoriteKey.Value/*cast due to .constrained prefix*/).ToString(), ((object)BrowserKey.Value/*cast due to .constrained prefix*/).ToString()));
		}

		private Vector2 SlotCentre(int slot)
		{
			//IL_001f: 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)
			float num = SlotAngle(slot, slots) * ((float)Math.PI / 180f);
			return new Vector2(Mathf.Sin(num), Mathf.Cos(num)) * MidRadius;
		}

		private void LayoutTabs()
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			float num = (0f - (tabControls.Sum(((Tab tab, Control control) t) => ((TMP_Text)t.control.Text).preferredWidth) + 34f * (float)(tabControls.Count - 1))) / 2f;
			foreach (var tabControl in tabControls)
			{
				Control item = tabControl.control;
				float preferredWidth = ((TMP_Text)item.Text).preferredWidth;
				item.Rect.sizeDelta = new Vector2(preferredWidth + 12f, 34f);
				item.Rect.anchoredPosition = new Vector2(num + preferredWidth / 2f, radius + 34f);
				num += preferredWidth + 34f;
			}
		}

		private void Build()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b4: Expected O, but got Unknown
			//IL_0500: Unknown result type (might be due to invalid IL or missing references)
			//IL_0525: Unknown result type (might be due to invalid IL or missing references)
			//IL_0561: Unknown result type (might be due to invalid IL or missing references)
			//IL_057e: Unknown result type (might be due to invalid IL or missing references)
			//IL_05be: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_063d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0660: Unknown result type (might be due to invalid IL or missing references)
			//IL_0670: Unknown result type (might be due to invalid IL or missing references)
			//IL_077c: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_07b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0820: Unknown result type (might be due to invalid IL or missing references)
			//IL_0866: Unknown result type (might be due to invalid IL or missing references)
			//IL_088d: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0905: Unknown result type (might be due to invalid IL or missing references)
			root = (RectTransform)((Component)this).transform;
			RectTransform val = (RectTransform)((Transform)root).parent;
			Rect rect = val.rect;
			float width = ((Rect)(ref rect)).width;
			rect = val.rect;
			float num = Mathf.Min(width, ((Rect)(ref rect)).height);
			float num2 = Mathf.Max(180f, num * 0.34f);
			if (labels.Count == slots && Mathf.Approximately(num2, radius))
			{
				return;
			}
			radius = num2;
			foreach (Transform item2 in (Transform)root)
			{
				Object.Destroy((Object)(object)((Component)item2).gameObject);
			}
			labels.Clear();
			icons.Clear();
			controls.Clear();
			tabControls.Clear();
			EnsureSprites();
			root.sizeDelta = new Vector2(radius * 2f, radius * 2f);
			NewImage("Shade", diskSprite, new Color(0f, 0f, 0f, 0.4f), radius * 2.06f);
			NewImage("Band", ringSprite, new Color(0.09f, 0.08f, 0.07f, 0.82f), radius * 2f);
			NewImage("Edge", edgeSprite, new Color(Orange.r, Orange.g, Orange.b, 0.35f), radius * 2f);
			highlight = NewImage("Highlight", ringSprite, new Color(Orange.r, Orange.g, Orange.b, 0.45f), radius * 2f);
			highlight.type = (Type)3;
			highlight.fillMethod = (FillMethod)4;
			highlight.fillOrigin = 2;
			highlight.fillClockwise = true;
			highlight.fillAmount = 1f / (float)slots;
			float bandWidth = BandWidth;
			float midRadius = MidRadius;
			float num3 = 2f * midRadius * Mathf.Sin((float)Math.PI / (float)slots);
			for (int i = 0; i < slots; i++)
			{
				float num4 = (SlotAngle(i, slots) + 180f / (float)slots) * ((float)Math.PI / 180f);
				Image obj = NewImage("Separator" + i, null, new Color(1f, 0.85f, 0.6f, 0.14f), 0f);
				((Graphic)obj).rectTransform.sizeDelta = new Vector2(2f, bandWidth * 0.92f);
				((Graphic)obj).rectTransform.anchoredPosition = new Vector2(Mathf.Sin(num4), Mathf.Cos(num4)) * midRadius;
				((Transform)((Graphic)obj).rectTransform).localRotation = Quaternion.Euler(0f, 0f, (0f - num4) * 57.29578f);
				Image val2 = NewImage("Icon" + i, null, Color.white, bandWidth * 0.34f);
				val2.preserveAspect = true;
				((Graphic)val2).rectTransform.anchoredPosition = SlotCentre(i) + new Vector2(0f, bandWidth * 0.17f);
				icons.Add(val2);
				TextMeshProUGUI val3 = NewText("Label" + i, 24f, 13f);
				((TMP_Text)val3).rectTransform.sizeDelta = new Vector2(Mathf.Min(bandWidth * 1.02f, num3 * 0.9f), bandWidth * 0.56f);
				((TMP_Text)val3).rectTransform.anchoredPosition = SlotCentre(i);
				labels.Add(val3);
			}
			float num5 = radius * 0.5f;
			previewDisk = NewImage("Preview", diskSprite, new Color(0.075f, 0.065f, 0.055f, 1f), num5 * 1.9f);
			((Component)previewDisk).gameObject.AddComponent<Mask>().showMaskGraphic = true;
			GameObject val4 = new GameObject("Texture", new Type[1] { typeof(RectTransform) });
			val4.transform.SetParent(((Component)previewDisk).transform, false);
			previewImage = val4.AddComponent<RawImage>();
			((Graphic)previewImage).raycastTarget = false;
			((Graphic)previewImage).rectTransform.sizeDelta = new Vector2(num5 * 1.9f, num5 * 1.9f);
			Image obj2 = NewImage("NameBack", null, new Color(0f, 0f, 0f, 0.5f), 0f);
			((Transform)((Graphic)obj2).rectTransform).SetParent(((Component)previewDisk).transform, false);
			((Graphic)obj2).rectTransform.sizeDelta = new Vector2(num5 * 1.9f, num5 * 0.44f);
			((Graphic)obj2).rectTransform.anchoredPosition = new Vector2(0f, (0f - num5) * 0.66f);
			nameText = NewText("Name", 26f, 14f);
			((TMP_Text)nameText).rectTransform.sizeDelta = new Vector2(num5 * 1.45f, num5 * 0.3f);
			((TMP_Text)nameText).rectTransform.anchoredPosition = new Vector2(0f, (0f - num5) * 0.6f);
			((TMP_Text)nameText).fontStyle = (FontStyles)1;
			((Graphic)nameText).color = Color.white;
			detailText = NewText("Detail", 15f, 11f);
			((TMP_Text)detailText).rectTransform.sizeDelta = new Vector2(num5 * 1.2f, num5 * 0.14f);
			((TMP_Text)detailText).rectTransform.anchoredPosition = new Vector2(0f, (0f - num5) * 0.8f);
			((Graphic)detailText).color = FavoriteColor;
			(Tab, string)[] tabs = Tabs;
			for (int j = 0; j < tabs.Length; j++)
			{
				(Tab, string) tuple = tabs[j];
				Tab tab = tuple.Item1;
				string item = tuple.Item2;
				Control control = NewControl("Tab_" + tab, Translations.Ui(item), 22f, delegate
				{
					SetTab(tab);
				});
				((TMP_Text)control.Text).enableAutoSizing = false;
				((TMP_Text)control.Text).fontSize = 22f;
				((TMP_Text)control.Text).textWrappingMode = (TextWrappingModes)0;
				tabControls.Add((tab, control));
			}
			pageText = NewText("Page", 18f, 12f);
			((TMP_Text)pageText).rectTransform.sizeDelta = new Vector2(220f, 30f);
			((TMP_Text)pageText).rectTransform.anchoredPosition = new Vector2(0f, 0f - radius - 26f);
			((Graphic)pageText).color = DimColor;
			previousPage = NewControl("PreviousPage", "<", 28f, delegate
			{
				SetPage(Page - 1);
			});
			previousPage.Rect.sizeDelta = new Vector2(44f, 36f);
			previousPage.Rect.anchoredPosition = new Vector2(-130f, 0f - radius - 26f);
			nextPage = NewControl("NextPage", ">", 28f, delegate
			{
				SetPage(Page + 1);
			});
			nextPage.Rect.sizeDelta = new Vector2(44f, 36f);
			nextPage.Rect.anchoredPosition = new Vector2(130f, 0f - radius - 26f);
			hintText = NewText("Hint", 15f, 10f);
			((TMP_Text)hintText).rectTransform.sizeDelta = new Vector2(radius * 2.6f, 26f);
			((TMP_Text)hintText).rectTransform.anchoredPosition = new Vector2(0f, 0f - radius - 58f);
			((Graphic)hintText).color = DimColor;
		}

		private Control NewControl(string name, string text, float fontSize, Action onClick)
		{
			TextMeshProUGUI val = NewText(name, fontSize, fontSize * 0.6f);
			((TMP_Text)val).text = text;
			Control control = new Control
			{
				Rect = ((TMP_Text)val).rectTransform,
				Text = val,
				OnClick = onClick
			};
			controls.Add(control);
			return control;
		}

		private Image NewImage(string name, Sprite sprite, Color color, float size)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)root, false);
			Image obj = val.AddComponent<Image>();
			obj.sprite = sprite;
			((Graphic)obj).color = color;
			((Graphic)obj).raycastTarget = false;
			((Graphic)obj).rectTransform.sizeDelta = new Vector2(size, size);
			return obj;
		}

		private TextMeshProUGUI NewText(string name, float maxSize, float minSize)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.SetActive(false);
			val.transform.SetParent((Transform)(object)root, false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val2).font = TmeRadial.Font;
			val.SetActive(true);
			((TMP_Text)val2).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val2).enableAutoSizing = true;
			((TMP_Text)val2).fontSizeMin = minSize;
			((TMP_Text)val2).fontSizeMax = maxSize;
			((TMP_Text)val2).textWrappingMode = (TextWrappingModes)1;