Decompiled source of Noxys Dynamic Radial Menu v1.0.4

NoxyRadialMenu.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using ModdingUtils.Utils;
using NoxyRadialMenu.UI;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace NoxyRadialMenu
{
	[BepInPlugin("com.noxy.rounds.radialmenu", "Noxy Radial Menu", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class RadialMenuPlugin : BaseUnityPlugin
	{
		private const string ModId = "com.noxy.rounds.radialmenu";

		private const string ModName = "Noxy Radial Menu";

		public const string Version = "1.0.0";

		public static RadialMenuPlugin instance;

		private void Awake()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			instance = this;
			Harmony val = new Harmony("com.noxy.rounds.radialmenu");
			val.PatchAll();
			GameObject val2 = new GameObject("NoxyRadialMenuManager");
			Object.DontDestroyOnLoad((Object)(object)val2);
			val2.AddComponent<RadialMenuManager>();
		}
	}
}
namespace NoxyRadialMenu.UI
{
	public class RadialMenuManager : MonoBehaviour
	{
		private GameObject canvasObj;

		private Canvas canvas;

		private GraphicRaycaster raycaster;

		private GameObject menuContainer;

		private List<GameObject> slices = new List<GameObject>();

		private List<Image> sliceImages = new List<Image>();

		private List<Text> sliceTexts = new List<Text>();

		public bool isOpen = false;

		public bool isApplyingCards = false;

		private List<int> selectedIndices = new List<int>();

		private int maxSelections = 1;

		private int hoveredIndex = -1;

		private List<string> currentOptions;

		private List<CardInfo> currentlyAppliedCards = new List<CardInfo>();

		private Dictionary<string, string> cardMapping = new Dictionary<string, string>();

		private bool hasBuiltCardMapping = false;

		public static bool IsMenuEnabled = false;

		private Coroutine activeCoroutine;

		public static RadialMenuManager Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			CreateCanvas();
			CreateMenuContainer();
			menuContainer.SetActive(false);
		}

		private void CreateCanvas()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			canvasObj = new GameObject("NoxyRadialMenuCanvas");
			canvasObj.transform.SetParent(((Component)this).transform);
			canvas = canvasObj.AddComponent<Canvas>();
			canvas.renderMode = (RenderMode)0;
			canvas.sortingOrder = 1000;
			CanvasScaler val = canvasObj.AddComponent<CanvasScaler>();
			val.uiScaleMode = (ScaleMode)1;
			val.referenceResolution = new Vector2(1920f, 1080f);
			raycaster = canvasObj.AddComponent<GraphicRaycaster>();
		}

		private void CreateMenuContainer()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			menuContainer = new GameObject("MenuContainer");
			menuContainer.transform.SetParent(canvasObj.transform, false);
			RectTransform val = menuContainer.AddComponent<RectTransform>();
			val.anchorMin = new Vector2(0.5f, 0.5f);
			val.anchorMax = new Vector2(0.5f, 0.5f);
			val.pivot = new Vector2(0.5f, 0.5f);
			val.anchoredPosition = Vector2.zero;
			val.sizeDelta = new Vector2(800f, 800f);
		}

		private void ClearSlices()
		{
			foreach (GameObject slice in slices)
			{
				Object.Destroy((Object)(object)slice);
			}
			slices.Clear();
			sliceImages.Clear();
			sliceTexts.Clear();
		}

		private void CreatePizzaSlices(List<string> options)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_008f: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Expected O, but got Unknown
			//IL_01a8: 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_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			ClearSlices();
			if (options != null && options.Count != 0)
			{
				int count = options.Count;
				float num = 360f / (float)count;
				Sprite sprite = CreateCircleSprite(256);
				for (int i = 0; i < count; i++)
				{
					GameObject val = new GameObject("Slice_" + i);
					val.transform.SetParent(menuContainer.transform, false);
					RectTransform val2 = val.AddComponent<RectTransform>();
					val2.anchorMin = new Vector2(0.5f, 0.5f);
					val2.anchorMax = new Vector2(0.5f, 0.5f);
					val2.pivot = new Vector2(0.5f, 0.5f);
					val2.anchoredPosition = Vector2.zero;
					val2.sizeDelta = new Vector2(600f, 600f);
					float num2 = 0f - (float)i * num + num / 2f;
					((Transform)val2).localRotation = Quaternion.Euler(0f, 0f, num2);
					Image val3 = val.AddComponent<Image>();
					val3.sprite = sprite;
					val3.type = (Type)3;
					val3.fillMethod = (FillMethod)4;
					val3.fillOrigin = 2;
					val3.fillAmount = 1f / (float)count;
					((Graphic)val3).color = new Color(0.1f, 0.1f, 0.1f, 0.9f);
					GameObject val4 = new GameObject("Text");
					val4.transform.SetParent(val.transform, false);
					RectTransform val5 = val4.AddComponent<RectTransform>();
					val5.sizeDelta = new Vector2(200f, 50f);
					float num3 = 200f;
					float num4 = num / 2f * ((float)Math.PI / 180f);
					val5.anchoredPosition = new Vector2(Mathf.Sin(num4) * num3, Mathf.Cos(num4) * num3);
					((Transform)val5).localRotation = Quaternion.Euler(0f, 0f, 0f - num2);
					Text val6 = val4.AddComponent<Text>();
					val6.text = options[i];
					val6.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
					val6.alignment = (TextAnchor)4;
					((Graphic)val6).color = Color.white;
					val6.fontSize = 24;
					slices.Add(val);
					sliceImages.Add(val3);
					sliceTexts.Add(val6);
				}
			}
		}

		private void BuildCardMapping()
		{
			if (hasBuiltCardMapping)
			{
				return;
			}
			hasBuiltCardMapping = true;
			cardMapping.Clear();
			CardInfo[] array = Resources.FindObjectsOfTypeAll<CardInfo>();
			foreach (CardInfo val in array)
			{
				string text = ((Object)((Component)val).gameObject).name.Replace("(Clone)", "").Trim();
				if (text.StartsWith("__JJK Cursed Techniques__"))
				{
					string key = text.Replace("__JJK Cursed Techniques__", "");
					if (!cardMapping.ContainsKey(key))
					{
						cardMapping.Add(key, text);
					}
				}
			}
			Debug.Log((object)("[NoxyRadialMenu] Dynamically loaded " + cardMapping.Count + " JJK cards."));
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)118) && !isOpen && !isApplyingCards && IsMenuEnabled)
			{
				BuildCardMapping();
				List<string> list = new List<string>(cardMapping.Keys);
				list.Sort();
				OpenMenu(list, 2);
			}
			else if (Input.GetKeyUp((KeyCode)118) && isOpen)
			{
				CloseMenu();
			}
			if (isOpen)
			{
				HandleMouseSelection();
				if (Input.GetMouseButtonDown(0) && hoveredIndex != -1)
				{
					ToggleSelection(hoveredIndex);
				}
			}
		}

		public void OpenMenu(List<string> options, int maxAllowed = 1)
		{
			maxSelections = maxAllowed;
			currentOptions = options;
			selectedIndices.RemoveAll((int i) => i >= options.Count);
			hoveredIndex = -1;
			CreatePizzaSlices(options);
			isOpen = true;
			menuContainer.SetActive(true);
			UpdateHighlights();
		}

		public List<int> CloseMenu()
		{
			isOpen = false;
			isApplyingCards = true;
			menuContainer.SetActive(false);
			List<int> list = new List<int>(selectedIndices);
			Debug.Log((object)("[NoxyRadialMenu] Selected Slots: " + string.Join(", ", list)));
			if (activeCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(activeCoroutine);
			}
			activeCoroutine = ((MonoBehaviour)this).StartCoroutine(ApplyCardsCoroutine(list));
			return list;
		}

		private Player GetLocalPlayer()
		{
			foreach (Player player in PlayerManager.instance.players)
			{
				if (player.data.view.IsMine)
				{
					return player;
				}
			}
			return null;
		}

		private IEnumerator ApplyCardsCoroutine(List<int> selectedSlots)
		{
			Player localPlayer = GetLocalPlayer();
			if ((Object)(object)localPlayer == (Object)null)
			{
				Debug.LogError((object)"[NoxyRadialMenu] No local player found!");
				isApplyingCards = false;
				yield break;
			}
			Debug.Log((object)("[NoxyRadialMenu] Local player found: " + localPlayer.playerID));
			List<string> selectedCardNames = new List<string>();
			foreach (int selectedSlot in selectedSlots)
			{
				if (selectedSlot >= 0 && selectedSlot < currentOptions.Count)
				{
					string key = currentOptions[selectedSlot];
					if (cardMapping.ContainsKey(key))
					{
						selectedCardNames.Add(cardMapping[key]);
					}
				}
			}
			Debug.Log((object)"[NoxyRadialMenu] Diffing current deck against new selections...");
			List<CardInfo> cardsToPurge = new List<CardInfo>();
			foreach (CardInfo currentCard in localPlayer.data.currentCards)
			{
				if ((Object)(object)currentCard != (Object)null && ((Object)((Component)currentCard).gameObject).name.Contains("__JJK Cursed Techniques__"))
				{
					string text = ((Object)((Component)currentCard).gameObject).name.Replace("(Clone)", "").Trim();
					if (selectedCardNames.Contains(text))
					{
						selectedCardNames.Remove(text);
						Debug.Log((object)("[NoxyRadialMenu] Keeping existing card: " + text));
					}
					else if (!cardsToPurge.Contains(currentCard))
					{
						cardsToPurge.Add(currentCard);
					}
				}
			}
			bool purgingYuta = false;
			foreach (CardInfo item in cardsToPurge)
			{
				if (((Object)((Component)item).gameObject).name.Contains("Rika Copy"))
				{
					purgingYuta = true;
					break;
				}
			}
			if (purgingYuta)
			{
				Component component = ((Component)localPlayer).GetComponent("YutaCopyBehaviour");
				MonoBehaviour val = (MonoBehaviour)(object)((component is MonoBehaviour) ? component : null);
				if ((Object)(object)val != (Object)null)
				{
					FieldInfo field = ((object)val).GetType().GetField("copiedCardInfo");
					if (field != null)
					{
						object? value = field.GetValue(val);
						CardInfo val2 = (CardInfo)((value is CardInfo) ? value : null);
						if ((Object)(object)val2 != (Object)null && !cardsToPurge.Contains(val2))
						{
							Debug.Log((object)"[NoxyRadialMenu] Purging Yuta's Copied Card along with Rika Copy.");
							cardsToPurge.Add(val2);
							field.SetValue(val, null);
						}
					}
				}
			}
			Debug.Log((object)("[NoxyRadialMenu] Found " + cardsToPurge.Count + " cards to purge."));
			foreach (CardInfo card in cardsToPurge)
			{
				Debug.Log((object)("[NoxyRadialMenu] Purging card: " + ((Object)card).name));
				try
				{
					Cards.instance.RemoveCardFromPlayer(localPlayer, card, (SelectionType)2);
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)("[NoxyRadialMenu] Failed to purge card: " + ex.Message));
				}
				yield return (object)new WaitForSecondsRealtime(0.6f);
			}
			foreach (string cardObjName in selectedCardNames)
			{
				Debug.Log((object)("[NoxyRadialMenu] Searching for NEW card: " + cardObjName));
				CardInfo cardToGive = null;
				CardInfo[] array = Resources.FindObjectsOfTypeAll<CardInfo>();
				foreach (CardInfo current3 in array)
				{
					if (((Object)((Component)current3).gameObject).name.Replace("(Clone)", "").Trim() == cardObjName)
					{
						cardToGive = current3;
						break;
					}
				}
				if ((Object)(object)cardToGive != (Object)null)
				{
					Debug.Log((object)("[NoxyRadialMenu] Found card! Applying: " + cardObjName));
					Cards.instance.AddCardToPlayer(localPlayer, cardToGive, false, "", 0f, 0f, true);
					yield return (object)new WaitForEndOfFrame();
				}
				else
				{
					Debug.LogError((object)("[NoxyRadialMenu] Card not found via FindObjectsOfTypeAll: " + cardObjName));
				}
			}
			isApplyingCards = false;
		}

		private void ToggleSelection(int index)
		{
			if (selectedIndices.Contains(index))
			{
				selectedIndices.Remove(index);
			}
			else
			{
				if (selectedIndices.Count >= maxSelections)
				{
					selectedIndices.RemoveAt(0);
				}
				selectedIndices.Add(index);
			}
			UpdateHighlights();
		}

		private void HandleMouseSelection()
		{
			//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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = Vector2.op_Implicit(Input.mousePosition);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor((float)Screen.width / 2f, (float)Screen.height / 2f);
			Vector2 val3 = val - val2;
			if (((Vector2)(ref val3)).magnitude < 50f)
			{
				if (hoveredIndex != -1)
				{
					hoveredIndex = -1;
					UpdateHighlights();
				}
				return;
			}
			float num = Mathf.Atan2(val3.x, val3.y) * 57.29578f;
			if (num < 0f)
			{
				num += 360f;
			}
			int count = slices.Count;
			float num2 = 360f / (float)count;
			float num3 = (num + num2 / 2f) % 360f;
			int num4 = Mathf.FloorToInt(num3 / num2);
			if (num4 != hoveredIndex)
			{
				hoveredIndex = num4;
				UpdateHighlights();
			}
		}

		private void UpdateHighlights()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < sliceImages.Count; i++)
			{
				bool flag = selectedIndices.Contains(i);
				bool flag2 = i == hoveredIndex;
				if (flag)
				{
					((Graphic)sliceImages[i]).color = new Color(0.6f, 0f, 1f, 1f);
					slices[i].transform.localScale = new Vector3(1.15f, 1.15f, 1.15f);
				}
				else if (flag2)
				{
					((Graphic)sliceImages[i]).color = new Color(0.4f, 0f, 0.6f, 1f);
					slices[i].transform.localScale = new Vector3(1.05f, 1.05f, 1.05f);
				}
				else
				{
					((Graphic)sliceImages[i]).color = new Color(0.1f, 0.1f, 0.1f, 0.9f);
					slices[i].transform.localScale = Vector3.one;
				}
			}
		}

		private Sprite CreateCircleSprite(int radius)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_00dc: 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_0093: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			int num = radius * 2;
			Texture2D val = new Texture2D(num, num, (TextureFormat)4, false);
			Color32[] array = (Color32[])(object)new Color32[num * num];
			Color32 val2 = default(Color32);
			((Color32)(ref val2))..ctor(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
			Color32 val3 = default(Color32);
			((Color32)(ref val3))..ctor((byte)0, (byte)0, (byte)0, (byte)0);
			for (int i = 0; i < num; i++)
			{
				for (int j = 0; j < num; j++)
				{
					float num2 = j - radius;
					float num3 = i - radius;
					if (num2 * num2 + num3 * num3 <= (float)(radius * radius))
					{
						array[i * num + j] = val2;
					}
					else
					{
						array[i * num + j] = val3;
					}
				}
			}
			val.SetPixels32(array);
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f));
		}
	}
}