Decompiled source of Radial Quickslots v0.5.1

Outward_RadialQuickslots.dll

Decompiled 21 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Outward_RadialQuickslots")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Outward_RadialQuickslots")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b2db2904-8c93-4647-becd-05e2ae56f3ce")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("com.poweredbypodcube.radialquickslots", "Radial Quickslots", "0.5.1")]
public class RadialHotbar : BaseUnityPlugin
{
	public static bool Open;

	public static RadialHotbar Instance;

	private ConfigEntry<KeyboardShortcut> _key;

	private ConfigEntry<float> _deadzone;

	private ConfigEntry<float> _maxRadius;

	private ConfigEntry<float> _sens;

	private ConfigEntry<float> _uiScale;

	private ConfigEntry<float> _ringRadius;

	private ConfigEntry<float> _slotSize;

	private ConfigEntry<float> _slotOpacity;

	private static int _closedFrame = -1;

	private Vector2 _accum;

	private int _hover = -1;

	private static readonly int[] _slots = new int[8] { 0, 1, 2, 3, 4, 5, 6, 7 };

	private GUIStyle _label;

	internal Character Local => CharacterManager.Instance.GetFirstLocalCharacter();

	private void Awake()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Expected O, but got Unknown
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Expected O, but got Unknown
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Expected O, but got Unknown
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Expected O, but got Unknown
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Expected O, but got Unknown
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Expected O, but got Unknown
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		_key = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "Hotkey", new KeyboardShortcut((KeyCode)113, Array.Empty<KeyCode>()), "Hold to open the radial, drag the mouse toward a slot, release to use it. While the radial is open (or this key is held) the game's own quickslot hotkeys are swallowed, so whatever key you pick here takes precedence over the stock binding.");
		_deadzone = ((BaseUnityPlugin)this).Config.Bind<float>("Selection", "Deadzone", 35f, new ConfigDescription("How far you must drag before a slot is selected. Releasing inside the deadzone does nothing. Values at or above Drag Range are clamped just below it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 140f), Array.Empty<object>()));
		_maxRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Selection", "DragRange", 140f, new ConfigDescription("Maximum drag distance (the cursor stops at this range). Smaller = less mouse travel to reach the edge.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(40f, 400f), Array.Empty<object>()));
		_sens = ((BaseUnityPlugin)this).Config.Bind<float>("Selection", "Sensitivity", 6f, new ConfigDescription("Mouse sensitivity while the radial is open.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f), Array.Empty<object>()));
		_uiScale = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "UIScale", 1f, new ConfigDescription("Overall size multiplier for the radial (slots, ring, text).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2.5f), Array.Empty<object>()));
		_ringRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "RingRadius", 210f, new ConfigDescription("Distance of the slots from the center, in pixels at 1080p.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(100f, 450f), Array.Empty<object>()));
		_slotSize = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "SlotSize", 104f, new ConfigDescription("Size of each slot box, in pixels at 1080p.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(40f, 200f), Array.Empty<object>()));
		_slotOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "SlotOpacity", 0.55f, new ConfigDescription("Opacity of the unselected slot backgrounds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		new Harmony("com.poweredbypodcube.radialquickslots").PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Radial Quickslots loaded");
	}

	private static bool MenuFocused(Character ch)
	{
		if ((Object)(object)ch.CharacterUI != (Object)null)
		{
			return ch.CharacterUI.IsMenuFocused;
		}
		return false;
	}

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

	public static bool SwallowStockQuickSlots()
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Instance == (Object)null)
		{
			return false;
		}
		Character local = Instance.Local;
		if ((Object)(object)local == (Object)null || MenuFocused(local))
		{
			return false;
		}
		if (Open || Time.frameCount == _closedFrame)
		{
			return true;
		}
		KeyboardShortcut value = Instance._key.Value;
		if ((int)((KeyboardShortcut)(ref value)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref value)).MainKey))
		{
			return ModsHeld(value);
		}
		return false;
	}

	private void Close(bool fire, Character ch, int slot)
	{
		Open = false;
		_closedFrame = Time.frameCount;
		if (fire && slot >= 0 && (Object)(object)ch != (Object)null && (Object)(object)ch.QuickSlotMngr != (Object)null)
		{
			ch.QuickSlotMngr.QuickSlotInput(slot);
		}
	}

	private void Update()
	{
		//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_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_005d: 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_00a1: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: 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_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: 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_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		Character local = Local;
		if ((Object)(object)local == (Object)null)
		{
			Open = false;
			return;
		}
		if ((Object)(object)local.QuickSlotMngr == (Object)null)
		{
			Open = false;
			return;
		}
		KeyboardShortcut value = _key.Value;
		KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey;
		if (Open && MenuFocused(local))
		{
			Open = false;
			return;
		}
		if (!Open && (int)mainKey != 0 && Input.GetKeyDown(mainKey) && ModsHeld(value) && !MenuFocused(local))
		{
			_accum = Vector2.zero;
			_hover = -1;
			Open = true;
		}
		if (!Open)
		{
			return;
		}
		if (!Application.isFocused || (int)mainKey == 0)
		{
			Close(fire: false, local, -1);
			return;
		}
		float value2 = _maxRadius.Value;
		float deadzone = Mathf.Min(_deadzone.Value, value2 - 1f);
		_accum += new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y")) * _sens.Value;
		_accum = Vector2.ClampMagnitude(_accum, value2);
		_hover = Pick(_accum, _slots.Length, deadzone);
		if (!Input.GetKey(mainKey))
		{
			Close(fire: true, local, (_hover >= 0) ? _slots[_hover] : (-1));
		}
	}

	private static int Pick(Vector2 v, int n, float deadzone)
	{
		//IL_000c: 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)
		if (((Vector2)(ref v)).magnitude < deadzone)
		{
			return -1;
		}
		float num = Mathf.Atan2(v.x, v.y) * 57.29578f;
		if (num < 0f)
		{
			num += 360f;
		}
		float num2 = 360f / (float)n;
		return Mathf.FloorToInt((num + num2 * 0.5f) % 360f / num2);
	}

	private void OnGUI()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Invalid comparison between Unknown and I4
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Expected O, but got Unknown
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_0323: Unknown result type (might be due to invalid IL or missing references)
		//IL_032d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0346: Unknown result type (might be due to invalid IL or missing references)
		//IL_0359: Unknown result type (might be due to invalid IL or missing references)
		//IL_0363: Unknown result type (might be due to invalid IL or missing references)
		//IL_0368: Unknown result type (might be due to invalid IL or missing references)
		//IL_036d: Unknown result type (might be due to invalid IL or missing references)
		//IL_036f: Unknown result type (might be due to invalid IL or missing references)
		//IL_037e: 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_017e: 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_0446: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_041b: Unknown result type (might be due to invalid IL or missing references)
		//IL_042d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0437: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: 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_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0288: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		if (!Open || (int)Event.current.type != 7)
		{
			return;
		}
		Character local = Local;
		if ((Object)(object)local == (Object)null)
		{
			return;
		}
		CharacterQuickSlotManager quickSlotMngr = local.QuickSlotMngr;
		if ((Object)(object)quickSlotMngr == (Object)null)
		{
			return;
		}
		float num = (float)Screen.height / 1080f * _uiScale.Value;
		float num2 = _slotSize.Value * num;
		float num3 = _ringRadius.Value * num;
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor((float)Screen.width / 2f, (float)Screen.height / 2f);
		if (_label == null)
		{
			_label = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)4,
				fontStyle = (FontStyle)1
			};
		}
		_label.fontSize = Mathf.RoundToInt(22f * num);
		string text = null;
		Rect val3 = default(Rect);
		for (int i = 0; i < _slots.Length; i++)
		{
			float num4 = 360f / (float)_slots.Length * (float)i * ((float)Math.PI / 180f);
			Vector2 val2 = val + new Vector2(Mathf.Sin(num4), 0f - Mathf.Cos(num4)) * num3;
			((Rect)(ref val3))..ctor(val2.x - num2 / 2f, val2.y - num2 / 2f, num2, num2);
			GUI.color = ((i == _hover) ? new Color(1f, 0.85f, 0.3f, 0.9f) : new Color(0f, 0f, 0f, _slotOpacity.Value));
			GUI.DrawTexture(val3, (Texture)(object)Texture2D.whiteTexture);
			QuickSlot quickSlot = quickSlotMngr.GetQuickSlot(_slots[i]);
			Item val4 = (((Object)(object)quickSlot != (Object)null && !quickSlot.IsFree) ? quickSlot.ActiveItem : null);
			Sprite val5 = (((Object)(object)val4 != (Object)null) ? val4.QuickSlotIcon : null);
			if ((Object)(object)val5 != (Object)null)
			{
				Texture2D texture = val5.texture;
				Rect textureRect = val5.textureRect;
				float num5 = ((Rect)(ref textureRect)).width / ((Rect)(ref textureRect)).height;
				float num6 = num2 - 12f * num;
				float num7 = num6;
				if (num5 > 1f)
				{
					num7 = num6 / num5;
				}
				else
				{
					num6 = num7 * num5;
				}
				Rect val6 = new Rect(((Rect)(ref val3)).center.x - num6 / 2f, ((Rect)(ref val3)).center.y - num7 / 2f, num6, num7);
				GUI.color = (Color)(quickSlot.IsLocked ? new Color(1f, 1f, 1f, 0.4f) : Color.white);
				GUI.DrawTextureWithTexCoords(val6, (Texture)(object)texture, new Rect(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height));
			}
			if (i == _hover && (Object)(object)val4 != (Object)null)
			{
				text = val4.Name;
			}
		}
		GUI.color = new Color(1f, 1f, 1f, 0.8f);
		Vector2 val7 = val + new Vector2(_accum.x, 0f - _accum.y) * (num3 / _maxRadius.Value) * 0.5f;
		GUI.DrawTexture(new Rect(val7.x - 4f * num, val7.y - 4f * num, 8f * num, 8f * num), (Texture)(object)Texture2D.whiteTexture);
		if (!string.IsNullOrEmpty(text))
		{
			Rect val8 = default(Rect);
			((Rect)(ref val8))..ctor(val.x - 200f * num, val.y - 20f * num, 400f * num, 40f * num);
			GUI.color = Color.black;
			GUI.Label(new Rect(((Rect)(ref val8)).x + 2f, ((Rect)(ref val8)).y + 2f, ((Rect)(ref val8)).width, ((Rect)(ref val8)).height), text, _label);
			GUI.color = Color.white;
			GUI.Label(val8, text, _label);
		}
		GUI.color = Color.white;
	}
}
[HarmonyPatch(typeof(LocalCharacterControl), "UpdateQuickSlots")]
internal static class SwallowStockHotkeys
{
	private static bool Prefix()
	{
		return !RadialHotbar.SwallowStockQuickSlots();
	}
}
[HarmonyPatch(typeof(ControlsInput), "RotateCameraHorizontal")]
internal static class NoLookH
{
	private static bool Prefix(ref float __result)
	{
		if (!RadialHotbar.Open)
		{
			return true;
		}
		__result = 0f;
		return false;
	}
}
[HarmonyPatch(typeof(ControlsInput), "RotateCameraVertical")]
internal static class NoLookV
{
	private static bool Prefix(ref float __result)
	{
		if (!RadialHotbar.Open)
		{
			return true;
		}
		__result = 0f;
		return false;
	}
}
[HarmonyPatch]
internal static class NoAttackWhileOpen
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		string[] array = new string[2] { "Attack1", "Attack2" };
		foreach (string text in array)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(ControlsInput), text, (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				yield return methodInfo;
			}
		}
	}

	private static bool Prefix(ref bool __result)
	{
		if (!RadialHotbar.Open)
		{
			return true;
		}
		__result = false;
		return false;
	}
}