Decompiled source of CrestWheel v1.1.1

CrestWheel.dll

Decompiled 19 hours 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 BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GlobalSettings;
using InControl;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CrestWheel")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("CrestWheel")]
[assembly: AssemblyTitle("CrestWheel")]
[assembly: AssemblyVersion("1.1.1.0")]
namespace CrestWheel;

public enum ControllerActivationButton
{
	Disabled,
	LeftStickButton,
	RightStickButton,
	DPadUp,
	DPadDown,
	DPadLeft,
	DPadRight,
	LeftTrigger,
	RightTrigger,
	LeftBumper,
	RightBumper,
	Action1,
	Action2,
	Action3,
	Action4,
	Action5,
	Action6,
	Action7,
	Action8,
	Action9,
	Action10,
	Action11,
	Action12,
	Back,
	Start,
	Select,
	Options,
	Pause,
	Menu,
	View,
	Share,
	Home,
	Plus,
	Minus,
	Create,
	Capture,
	TouchPadButton,
	Paddle1,
	Paddle2,
	Paddle3,
	Paddle4,
	Command,
	LeftCommand,
	RightCommand
}
public enum ControllerSelectionInput
{
	RightStick,
	LeftStick,
	DPad,
	None
}
internal enum ActivationSource
{
	None,
	Controller,
	Keyboard
}
[BepInPlugin("moriko.silksong.crestwheel", "Crest Wheel", "1.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class CrestWheelPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "moriko.silksong.crestwheel";

	public const string PluginName = "Crest Wheel";

	public const string PluginVersion = "1.1.1";

	private const float OpeningAnimationDuration = 0.25f;

	private static readonly string[] FixedCrestSlotNames = new string[7] { "Hunter", "Wanderer", "Reaper", "Warrior", "Toolmaster", "Witch", "Spell" };

	private static readonly FieldInfo InputActionsField = typeof(InputHandler).GetField("inputActions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo InputBlockersField = typeof(HeroController).GetField("inputBlockers", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo HeroRendererField = typeof(HeroController).GetField("renderer", BindingFlags.Instance | BindingFlags.NonPublic);

	private readonly List<CrestEntry> entries = new List<CrestEntry>();

	private ConfigEntry<bool> enabledConfig;

	private ConfigEntry<ControllerActivationButton> controllerActivationButtonConfig;

	private ConfigEntry<ControllerSelectionInput> controllerSelectionInputConfig;

	private ConfigEntry<float> activationHoldDurationConfig;

	private ConfigEntry<float> deadzoneConfig;

	private ConfigEntry<Key> keyboardActivationKeyConfig;

	private ConfigEntry<Key> keyboardUpKeyConfig;

	private ConfigEntry<Key> keyboardDownKeyConfig;

	private ConfigEntry<Key> keyboardLeftKeyConfig;

	private ConfigEntry<Key> keyboardRightKeyConfig;

	private ConfigEntry<Key> keyboardCancelKeyConfig;

	private ConfigEntry<float> wheelScaleConfig;

	private ConfigEntry<float> backgroundDimConfig;

	private ConfigEntry<int> settingsRevisionConfig;

	private RandomizerCompatibility randomizer;

	private CrestWheelView view;

	private HeroController blockedHero;

	private InputDevice activationDevice;

	private InputControl activationControl;

	private ActivationSource activationSource;

	private bool isOpen;

	private bool isActivationPending;

	private bool hasAimed;

	private int selectedIndex;

	private int equippedIndex;

	private float openProgress;

	private float activationHeldTime;

	private bool keyboardActivationPressed;

	private bool keyboardActivationWasPressed;

	private bool keyboardActivationWasReleased;

	private bool keyboardCancelPressed;

	private bool keyboardCancelWasPressed;

	internal static CrestWheelPlugin Instance { get; private set; }

	internal static ManualLogSource Log { get; private set; }

	private void Awake()
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Expected O, but got Unknown
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Expected O, but got Unknown
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Expected O, but got Unknown
		//IL_0228: Unknown result type (might be due to invalid IL or missing references)
		//IL_0232: Expected O, but got Unknown
		//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Invalid comparison between Unknown and I4
		//IL_03e5: 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_041f: Unknown result type (might be due to invalid IL or missing references)
		//IL_043c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0459: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d0: Invalid comparison between Unknown and I4
		//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02df: Invalid comparison between Unknown and I4
		//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ee: Invalid comparison between Unknown and I4
		//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fd: Invalid comparison between Unknown and I4
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		enabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the crest wheel.");
		controllerActivationButtonConfig = ((BaseUnityPlugin)this).Config.Bind<ControllerActivationButton>("Controller", "Activation Button", ControllerActivationButton.LeftStickButton, "Controller button held to open the wheel and released to equip. Set Disabled for keyboard-only use.");
		activationHoldDurationConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Controller", "Hold Duration", 0f, new ConfigDescription("How many seconds the configured controller button or keyboard key must be held before the wheel begins opening. Set to 0 for immediate opening.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
		controllerSelectionInputConfig = ((BaseUnityPlugin)this).Config.Bind<ControllerSelectionInput>("Controller", "Selection Input", ControllerSelectionInput.RightStick, "Controller input used to aim around the wheel.");
		deadzoneConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Controller", "Selection Deadzone", 0.45f, new ConfigDescription("How far an analog selection stick must move before a crest is selected.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.15f, 0.9f), Array.Empty<object>()));
		keyboardActivationKeyConfig = ((BaseUnityPlugin)this).Config.Bind<Key>("Keyboard", "Activation Key", (Key)4, "Keyboard key held to open the wheel and released to equip. Set None to disable keyboard activation.");
		keyboardUpKeyConfig = ((BaseUnityPlugin)this).Config.Bind<Key>("Keyboard", "Selection Up", (Key)58, "Keyboard key used to aim upward.");
		keyboardDownKeyConfig = ((BaseUnityPlugin)this).Config.Bind<Key>("Keyboard", "Selection Down", (Key)54, "Keyboard key used to aim downward.");
		keyboardLeftKeyConfig = ((BaseUnityPlugin)this).Config.Bind<Key>("Keyboard", "Selection Left", (Key)36, "Keyboard key used to aim left.");
		keyboardRightKeyConfig = ((BaseUnityPlugin)this).Config.Bind<Key>("Keyboard", "Selection Right", (Key)39, "Keyboard key used to aim right.");
		keyboardCancelKeyConfig = ((BaseUnityPlugin)this).Config.Bind<Key>("Keyboard", "Cancel Key", (Key)13, "Keyboard key that closes the wheel without switching. Set None to rely on the game's normal cancel binding.");
		wheelScaleConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "Wheel Scale", 1f, new ConfigDescription("Scale of the crest wheel.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.65f, 1.5f), Array.Empty<object>()));
		backgroundDimConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "Background Dimming", 0.24f, new ConfigDescription("Opacity of the screen dim behind the wheel.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.8f), Array.Empty<object>()));
		settingsRevisionConfig = ((BaseUnityPlugin)this).Config.Bind<int>("Internal", "Settings Revision", 0, "Tracks one-time migrations of development-build defaults.");
		if (settingsRevisionConfig.Value < 1)
		{
			if (Mathf.Approximately(backgroundDimConfig.Value, 0.42f))
			{
				backgroundDimConfig.Value = 0.24f;
			}
			settingsRevisionConfig.Value = 1;
			((BaseUnityPlugin)this).Config.Save();
		}
		if (settingsRevisionConfig.Value < 2)
		{
			if ((int)keyboardActivationKeyConfig.Value == 8 && (int)keyboardUpKeyConfig.Value == 85 && (int)keyboardDownKeyConfig.Value == 86 && (int)keyboardLeftKeyConfig.Value == 83 && (int)keyboardRightKeyConfig.Value == 84)
			{
				keyboardActivationKeyConfig.Value = (Key)4;
				keyboardUpKeyConfig.Value = (Key)58;
				keyboardDownKeyConfig.Value = (Key)54;
				keyboardLeftKeyConfig.Value = (Key)36;
				keyboardRightKeyConfig.Value = (Key)39;
			}
			settingsRevisionConfig.Value = 2;
			((BaseUnityPlugin)this).Config.Save();
		}
		randomizer = new RandomizerCompatibility(((BaseUnityPlugin)this).Logger);
		if (InputActionsField == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Crest Wheel could not locate InputHandler.inputActions; the game's normal menu-cancel binding will be unavailable, but configured wheel bindings will still work.");
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Crest Wheel 1.1.1 loaded. Controller: " + $"{controllerActivationButtonConfig.Value} + " + $"{controllerSelectionInputConfig.Value}; keyboard: " + $"{keyboardActivationKeyConfig.Value} + " + $"{keyboardUpKeyConfig.Value}/" + $"{keyboardLeftKeyConfig.Value}/" + $"{keyboardDownKeyConfig.Value}/" + $"{keyboardRightKeyConfig.Value}; " + $"hold duration: {GetActivationHoldDuration():0.00}s."));
	}

	private void Update()
	{
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		RefreshKeyboardState();
		HeroActions heroActions = GetHeroActions();
		if (!enabledConfig.Value)
		{
			CloseWheel();
			return;
		}
		if (!isOpen)
		{
			InputDevice device;
			InputControl control;
			if (!CanOpenNow())
			{
				CancelPendingActivation();
			}
			else if (isActivationPending)
			{
				if (WasActivationReleased() || !IsActivationPressed())
				{
					CancelPendingActivation();
					return;
				}
				activationHeldTime += Time.unscaledDeltaTime;
				if (activationHeldTime >= GetActivationHoldDuration())
				{
					isActivationPending = false;
					activationHeldTime = 0f;
					if (!TryOpenWheel())
					{
						ClearActivationSource();
					}
				}
			}
			else if (TryGetPressedControllerActivation(out device, out control))
			{
				BeginActivation(ActivationSource.Controller, device, control);
			}
			else if (keyboardActivationWasPressed)
			{
				BeginActivation(ActivationSource.Keyboard, null, null);
			}
			return;
		}
		openProgress = Mathf.MoveTowards(openProgress, 1f, Time.unscaledDeltaTime / 0.25f);
		view?.SetOpenProgress(openProgress);
		if (!CanRemainOpen())
		{
			CloseWheel();
			return;
		}
		UpdateSelection(GetSelectionInput());
		if (keyboardCancelWasPressed || WasNativeCancelPressed(heroActions))
		{
			CloseWheel();
		}
		else if (WasActivationReleased() || !IsActivationPressed())
		{
			if (openProgress >= 1f && hasAimed)
			{
				ConfirmSelection();
			}
			else
			{
				CloseWheel();
			}
		}
	}

	private void RefreshKeyboardState()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		bool flag = keyboardActivationPressed;
		ConfigEntry<Key> obj = keyboardActivationKeyConfig;
		keyboardActivationPressed = IsKeyboardKeyPressed((Key)((obj != null) ? ((int)obj.Value) : 0));
		keyboardActivationWasPressed = keyboardActivationPressed && !flag;
		keyboardActivationWasReleased = !keyboardActivationPressed && flag;
		bool flag2 = keyboardCancelPressed;
		ConfigEntry<Key> obj2 = keyboardCancelKeyConfig;
		keyboardCancelPressed = IsKeyboardKeyPressed((Key)((obj2 != null) ? ((int)obj2.Value) : 0));
		keyboardCancelWasPressed = keyboardCancelPressed && !flag2;
	}

	private static bool IsKeyboardKeyPressed(Key key)
	{
		//IL_0000: 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 ((int)key == 0)
		{
			return false;
		}
		try
		{
			return InputManager.KeyboardProvider != null && InputManager.KeyboardProvider.GetKeyIsPressed(key);
		}
		catch
		{
			return false;
		}
	}

	private void BeginActivation(ActivationSource source, InputDevice device, InputControl control)
	{
		activationSource = source;
		activationDevice = device;
		activationControl = control;
		activationHeldTime = 0f;
		if (GetActivationHoldDuration() <= 0f)
		{
			if (!TryOpenWheel())
			{
				ClearActivationSource();
			}
		}
		else
		{
			isActivationPending = true;
		}
	}

	private bool TryGetPressedControllerActivation(out InputDevice device, out InputControl control)
	{
		//IL_0007: 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_0021: Unknown result type (might be due to invalid IL or missing references)
		device = null;
		control = null;
		InputControlType controllerActivationControlType = GetControllerActivationControlType();
		if ((int)controllerActivationControlType == 0)
		{
			return false;
		}
		try
		{
			InputDevice activeDevice = InputManager.ActiveDevice;
			if (activeDevice == null)
			{
				return false;
			}
			InputControl val = activeDevice[controllerActivationControlType];
			if (val == null || !((OneAxisInputControl)val).WasPressed)
			{
				return false;
			}
			device = activeDevice;
			control = val;
			return true;
		}
		catch
		{
			return false;
		}
	}

	private InputControlType GetControllerActivationControlType()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		ControllerActivationButton controllerActivationButton = controllerActivationButtonConfig?.Value ?? ControllerActivationButton.LeftStickButton;
		if (controllerActivationButton == ControllerActivationButton.Disabled)
		{
			return (InputControlType)0;
		}
		if (!Enum.TryParse<InputControlType>(controllerActivationButton.ToString(), out InputControlType result))
		{
			return (InputControlType)5;
		}
		return result;
	}

	private Vector2 GetSelectionInput()
	{
		//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_0007: 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_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_005d: 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_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//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)
		Vector2 keyboardSelectionInput = GetKeyboardSelectionInput();
		Vector2 result = Vector2.zero;
		try
		{
			InputDevice val = activationDevice ?? InputManager.ActiveDevice;
			if (val != null)
			{
				result = (Vector2)((controllerSelectionInputConfig?.Value ?? ControllerSelectionInput.RightStick) switch
				{
					ControllerSelectionInput.LeftStick => val.LeftStick.Vector, 
					ControllerSelectionInput.DPad => val.DPad.Vector, 
					ControllerSelectionInput.None => Vector2.zero, 
					_ => val.RightStick.Vector, 
				});
			}
		}
		catch
		{
			result = Vector2.zero;
		}
		if (!(((Vector2)(ref keyboardSelectionInput)).sqrMagnitude >= ((Vector2)(ref result)).sqrMagnitude))
		{
			return result;
		}
		return keyboardSelectionInput;
	}

	private Vector2 GetKeyboardSelectionInput()
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		float num = 0f;
		float num2 = 0f;
		ConfigEntry<Key> obj = keyboardLeftKeyConfig;
		if (IsKeyboardKeyPressed((Key)((obj == null) ? 36 : ((int)obj.Value))))
		{
			num -= 1f;
		}
		ConfigEntry<Key> obj2 = keyboardRightKeyConfig;
		if (IsKeyboardKeyPressed((Key)((obj2 == null) ? 39 : ((int)obj2.Value))))
		{
			num += 1f;
		}
		ConfigEntry<Key> obj3 = keyboardDownKeyConfig;
		if (IsKeyboardKeyPressed((Key)((obj3 == null) ? 54 : ((int)obj3.Value))))
		{
			num2 -= 1f;
		}
		ConfigEntry<Key> obj4 = keyboardUpKeyConfig;
		if (IsKeyboardKeyPressed((Key)((obj4 == null) ? 58 : ((int)obj4.Value))))
		{
			num2 += 1f;
		}
		return new Vector2(num, num2);
	}

	private static bool WasNativeCancelPressed(HeroActions actions)
	{
		try
		{
			return actions != null && ((OneAxisInputControl)actions.MenuCancel).WasPressed;
		}
		catch
		{
			return false;
		}
	}

	private void LateUpdate()
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		if (isOpen && (Object)(object)blockedHero != (Object)null)
		{
			view?.SetWorldCenter(GetHeroCenter(blockedHero));
		}
	}

	private void OnDisable()
	{
		CloseWheel();
	}

	private void OnDestroy()
	{
		CloseWheel();
		view?.Dispose();
		view = null;
		if (Instance == this)
		{
			Instance = null;
			Log = null;
		}
	}

	private bool TryOpenWheel()
	{
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		if (isOpen || !CanOpenNow())
		{
			return false;
		}
		try
		{
			BuildFixedCrestSlots();
			if (entries.Count != FixedCrestSlotNames.Length)
			{
				return false;
			}
			PlayerData instance = PlayerData.instance;
			equippedIndex = FindEntryIndex(instance.CurrentCrestID);
			if (equippedIndex < 0 || !entries[equippedIndex].IsOwned)
			{
				return false;
			}
			selectedIndex = equippedIndex;
			hasAimed = false;
			openProgress = 0f;
			blockedHero = HeroController.instance;
			blockedHero.AddInputBlocker((object)this);
			blockedHero.move_input = 0f;
			blockedHero.vertical_input = 0f;
			if (view == null)
			{
				view = new CrestWheelView();
			}
			view.Show(entries, equippedIndex, selectedIndex, hasAimed: false, wheelScaleConfig.Value, backgroundDimConfig.Value);
			view.SetWorldCenter(GetHeroCenter(blockedHero));
			isOpen = true;
			return true;
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"Could not open the crest wheel: {arg}");
			ReleaseInputBlocker();
			ClearActivationSource();
			view?.Hide();
			entries.Clear();
			isOpen = false;
			return false;
		}
	}

	private void UpdateSelection(Vector2 input)
	{
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Clamp(deadzoneConfig.Value, 0.15f, 0.9f);
		if (((Vector2)(ref input)).sqrMagnitude < num * num || entries.Count == 0)
		{
			if (hasAimed)
			{
				hasAimed = false;
				view?.SetSelection(selectedIndex, equippedIndex, hasAimed: false);
			}
			return;
		}
		int num2 = Mathf.RoundToInt(Mathf.Repeat(90f - Mathf.Atan2(input.y, input.x) * 57.29578f, 360f) / (360f / (float)entries.Count)) % entries.Count;
		bool num3 = num2 != selectedIndex || !hasAimed;
		selectedIndex = num2;
		hasAimed = true;
		if (num3)
		{
			view?.SetSelection(selectedIndex, equippedIndex, hasAimed: true);
		}
	}

	private void ConfirmSelection()
	{
		if (isOpen)
		{
			ToolCrest val = ((hasAimed && selectedIndex >= 0 && selectedIndex < entries.Count && entries[selectedIndex].IsOwned) ? entries[selectedIndex].Crest : null);
			CloseWheel();
			if ((Object)(object)val != (Object)null)
			{
				TryEquipCrest(val);
			}
		}
	}

	private void CloseWheel()
	{
		isOpen = false;
		isActivationPending = false;
		view?.Hide();
		NeutralizeHeroAxes(blockedHero);
		ReleaseInputBlocker();
		entries.Clear();
		hasAimed = false;
		openProgress = 0f;
		activationHeldTime = 0f;
		ClearActivationSource();
	}

	private void CancelPendingActivation()
	{
		isActivationPending = false;
		activationHeldTime = 0f;
		ClearActivationSource();
	}

	private void ClearActivationSource()
	{
		activationSource = ActivationSource.None;
		activationDevice = null;
		activationControl = null;
	}

	private float GetActivationHoldDuration()
	{
		return Mathf.Clamp(activationHoldDurationConfig?.Value ?? 0f, 0f, 5f);
	}

	private bool TryEquipCrest(ToolCrest requestedCrest)
	{
		if ((Object)(object)requestedCrest == (Object)null || !CanRemainOpen())
		{
			return false;
		}
		string name = requestedCrest.name;
		BuildFixedCrestSlots();
		int num = FindEntryIndex(name);
		if (num < 0 || !entries[num].IsOwned || randomizer.IsSwitchBlocked())
		{
			return false;
		}
		ToolCrest crest = entries[num].Crest;
		PlayerData instance = PlayerData.instance;
		HeroController instance2 = HeroController.instance;
		if ((Object)(object)crest == (Object)null || instance == null || (Object)(object)instance2 == (Object)null)
		{
			return false;
		}
		if (string.Equals(instance.CurrentCrestID, crest.name, StringComparison.Ordinal))
		{
			return true;
		}
		try
		{
			ToolItemManager.SetEquippedCrest(crest.name);
			instance.IsCurrentCrestTemp = false;
			ToolItemManager.RefreshEquippedState();
			ToolItemManager.SendEquippedChangedEvent(true);
			randomizer.AfterCrestEquipped();
			NeutralizeHeroAxes(instance2);
			bool num2 = string.Equals(instance.CurrentCrestID, crest.name, StringComparison.Ordinal);
			if (num2)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Equipped crest from wheel: " + crest.name));
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Crest switch was rejected: " + crest.name));
			}
			return num2;
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"Could not equip crest '{crest.name}': {arg}");
			return false;
		}
	}

	private void BuildFixedCrestSlots()
	{
		entries.Clear();
		randomizer.RefreshSnapshot();
		List<ToolCrest> allCrests = ToolItemManager.GetAllCrests();
		if (allCrests == null)
		{
			return;
		}
		List<ToolCrest>[] array = new List<ToolCrest>[FixedCrestSlotNames.Length];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = new List<ToolCrest>();
		}
		foreach (ToolCrest item in allCrests)
		{
			if (!((Object)(object)item == (Object)null) && !string.IsNullOrEmpty(item.name) && !IsTemporarySpecialCrest(item))
			{
				int fixedCrestSlotIndex = GetFixedCrestSlotIndex(item.name);
				if (fixedCrestSlotIndex >= 0)
				{
					array[fixedCrestSlotIndex].Add(item);
				}
			}
		}
		string currentCrestId = PlayerData.instance?.CurrentCrestID;
		for (int j = 0; j < FixedCrestSlotNames.Length; j++)
		{
			ToolCrest crest = ChooseCrestForFixedSlot(array[j], currentCrestId);
			entries.Add(new CrestEntry(crest, FixedCrestSlotNames[j], j, IsCrestSelectable(crest, currentCrestId)));
		}
	}

	private ToolCrest ChooseCrestForFixedSlot(List<ToolCrest> candidates, string currentCrestId)
	{
		if (candidates == null || candidates.Count == 0)
		{
			return null;
		}
		ToolCrest val = null;
		ToolCrest val2 = null;
		ToolCrest val3 = null;
		for (int i = 0; i < candidates.Count; i++)
		{
			ToolCrest val4 = candidates[i];
			if (!((Object)(object)val4 == (Object)null))
			{
				if (string.Equals(val4.name, currentCrestId, StringComparison.Ordinal))
				{
					return val4;
				}
				if (IsCrestSelectable(val4, currentCrestId))
				{
					val = val4;
				}
				if ((Object)(object)val2 == (Object)null && val4.IsBaseVersion)
				{
					val2 = val4;
				}
				if ((Object)(object)val3 == (Object)null && val4.IsVisible && !val4.IsHidden)
				{
					val3 = val4;
				}
			}
		}
		return val ?? val2 ?? val3 ?? candidates[0];
	}

	private bool IsCrestSelectable(ToolCrest crest, string currentCrestId)
	{
		if ((Object)(object)crest == (Object)null || crest.IsHidden || !crest.IsUnlocked)
		{
			return false;
		}
		bool flag = string.Equals(crest.name, currentCrestId, StringComparison.Ordinal);
		if (crest.IsVisible || flag)
		{
			return randomizer.IsCrestOwned(crest);
		}
		return false;
	}

	private static bool IsTemporarySpecialCrest(ToolCrest crest)
	{
		if ((Object)(object)crest == (Object)null)
		{
			return false;
		}
		try
		{
			if (crest == Gameplay.CursedCrest || crest == Gameplay.CloaklessCrest)
			{
				return true;
			}
		}
		catch
		{
		}
		string text = crest.name ?? string.Empty;
		if (text.IndexOf("Cloakless", StringComparison.OrdinalIgnoreCase) < 0)
		{
			return text.IndexOf("Cursed", StringComparison.OrdinalIgnoreCase) >= 0;
		}
		return true;
	}

	private int FindEntryIndex(string crestName)
	{
		int fixedCrestSlotIndex = GetFixedCrestSlotIndex(crestName);
		if (fixedCrestSlotIndex < 0 || fixedCrestSlotIndex >= entries.Count)
		{
			return -1;
		}
		if (entries[fixedCrestSlotIndex].FixedSlotIndex != fixedCrestSlotIndex)
		{
			return -1;
		}
		return fixedCrestSlotIndex;
	}

	private static int GetFixedCrestSlotIndex(string crestName)
	{
		if (string.IsNullOrEmpty(crestName))
		{
			return -1;
		}
		if (crestName.StartsWith("Hunter", StringComparison.OrdinalIgnoreCase))
		{
			return 0;
		}
		for (int i = 1; i < FixedCrestSlotNames.Length; i++)
		{
			if (string.Equals(FixedCrestSlotNames[i], crestName, StringComparison.OrdinalIgnoreCase))
			{
				return i;
			}
		}
		return -1;
	}

	private bool CanOpenNow()
	{
		if (CanUseWheelRuntime() && (Object)(object)HeroController.instance != (Object)null)
		{
			return !HeroController.instance.IsInputBlocked();
		}
		return false;
	}

	private bool CanRemainOpen()
	{
		if (CanUseWheelRuntime())
		{
			return !HasForeignInputBlocker();
		}
		return false;
	}

	private bool CanUseWheelRuntime()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Invalid comparison between Unknown and I4
		try
		{
			GameManager silentInstance = GameManager.SilentInstance;
			HeroController instance = HeroController.instance;
			PlayerData instance2 = PlayerData.instance;
			return (Object)(object)silentInstance != (Object)null && (int)silentInstance.GameState == 4 && silentInstance.IsGameplayScene() && (Object)(object)instance != (Object)null && instance.CanTakeControl() && instance2 != null && !instance2.IsCurrentCrestTemp && !instance2.IsAnyCursed && !ToolItemManager.IsCursed && !ToolItemManager.IsInCutscene && !ToolItemManager.IsChangingActiveState && !randomizer.IsSwitchBlocked();
		}
		catch
		{
			return false;
		}
	}

	private bool HasForeignInputBlocker()
	{
		HeroController instance = HeroController.instance;
		if ((Object)(object)instance == (Object)null || InputBlockersField == null)
		{
			return false;
		}
		try
		{
			if (!(InputBlockersField.GetValue(instance) is IEnumerable enumerable))
			{
				return false;
			}
			foreach (object item in enumerable)
			{
				Object val = (Object)((item is Object) ? item : null);
				if ((val == null || !(val == (Object)null)) && item != null && item != this)
				{
					return true;
				}
			}
		}
		catch
		{
		}
		return false;
	}

	private static HeroActions GetHeroActions()
	{
		try
		{
			GameManager silentInstance = GameManager.SilentInstance;
			InputHandler val = ((silentInstance != null) ? silentInstance.inputHandler : null);
			return (HeroActions)(((Object)(object)val == (Object)null || InputActionsField == null) ? null : /*isinst with value type is only supported in some contexts*/);
		}
		catch
		{
			return null;
		}
	}

	private bool WasActivationReleased()
	{
		if (activationSource == ActivationSource.Keyboard)
		{
			return keyboardActivationWasReleased;
		}
		if (activationSource != ActivationSource.Controller)
		{
			return false;
		}
		try
		{
			return activationControl != null && ((OneAxisInputControl)activationControl).WasReleased;
		}
		catch
		{
			return false;
		}
	}

	private bool IsActivationPressed()
	{
		if (activationSource == ActivationSource.Keyboard)
		{
			return keyboardActivationPressed;
		}
		if (activationSource != ActivationSource.Controller)
		{
			return false;
		}
		try
		{
			return activationControl != null && ((OneAxisInputControl)activationControl).IsPressed;
		}
		catch
		{
			return false;
		}
	}

	private static Vector3 GetHeroCenter(HeroController hero)
	{
		//IL_007f: 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_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: 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_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)hero == (Object)null)
		{
			return Vector3.zero;
		}
		try
		{
			Bounds bounds = hero.Bounds;
			Vector3 center = ((Bounds)(ref bounds)).center;
			object? obj = HeroRendererField?.GetValue(hero);
			Renderer val = (Renderer)((obj is Renderer) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				bounds = val.bounds;
				if (((Bounds)(ref bounds)).size.y > 0f)
				{
					bounds = val.bounds;
					center.y = ((Bounds)(ref bounds)).center.y;
				}
			}
			return center;
		}
		catch
		{
			return ((Component)hero).transform.position + Vector3.up;
		}
	}

	private static void NeutralizeHeroAxes(HeroController hero)
	{
		if ((Object)(object)hero == (Object)null)
		{
			return;
		}
		try
		{
			hero.move_input = 0f;
			hero.vertical_input = 0f;
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogWarning((object)("Could not neutralize input after crest wheel: " + ex.Message));
			}
		}
	}

	private void ReleaseInputBlocker()
	{
		if ((Object)(object)blockedHero == (Object)null)
		{
			return;
		}
		try
		{
			blockedHero.RemoveInputBlocker((object)this);
		}
		catch
		{
		}
		finally
		{
			blockedHero = null;
		}
	}
}
internal sealed class CrestEntry
{
	internal ToolCrest Crest { get; }

	internal string InternalName { get; }

	internal string SlotName { get; }

	internal int FixedSlotIndex { get; }

	internal bool IsOwned { get; }

	internal Sprite Sprite
	{
		get
		{
			if ((Object)(object)Crest == (Object)null)
			{
				return null;
			}
			if (!((Object)(object)Crest.CrestSilhouette != (Object)null))
			{
				return Crest.CrestSprite;
			}
			return Crest.CrestSilhouette;
		}
	}

	internal CrestEntry(ToolCrest crest, string slotName, int fixedSlotIndex, bool isOwned)
	{
		Crest = crest;
		InternalName = ((crest != null) ? crest.name : null) ?? slotName ?? string.Empty;
		SlotName = slotName ?? InternalName;
		FixedSlotIndex = fixedSlotIndex;
		IsOwned = isOwned;
	}
}
internal sealed class CrestWheelView : IDisposable
{
	private static readonly Color NormalIcon = new Color(0.58f, 0.56f, 0.52f, 0.92f);

	private static readonly Color EquippedIcon = new Color(0.8f, 0.74f, 0.6f, 1f);

	private static readonly Color SelectedIcon = new Color(0.95f, 0.87f, 0.76f, 1f);

	private static readonly Color LockedIcon = new Color(0.36f, 0.37f, 0.39f, 0.46f);

	private static readonly Color LockedHoveredIcon = new Color(0.46f, 0.47f, 0.49f, 0.68f);

	private readonly List<GameObject> iconRoots = new List<GameObject>();

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

	private readonly List<CrestEntry> entries = new List<CrestEntry>();

	private GameObject canvasObject;

	private GameObject wheelObject;

	private RectTransform canvasRect;

	private RectTransform wheelRect;

	private CanvasGroup canvasGroup;

	private Image dimImage;

	private RadialRingGraphic ringGraphic;

	private float configuredScale = 1f;

	internal void Show(IReadOnlyList<CrestEntry> sourceEntries, int equippedIndex, int selectedIndex, bool hasAimed, float scale, float dimAmount)
	{
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		EnsureCanvas();
		entries.Clear();
		for (int i = 0; i < sourceEntries.Count; i++)
		{
			entries.Add(sourceEntries[i]);
		}
		configuredScale = Mathf.Clamp(scale, 0.65f, 1.5f);
		((Graphic)dimImage).color = new Color(0.008f, 0.006f, 0.012f, Mathf.Clamp(dimAmount, 0f, 0.8f));
		BuildIcons();
		ringGraphic.Configure(entries, selectedIndex, equippedIndex, hasAimed);
		SetSelection(selectedIndex, equippedIndex, hasAimed);
		canvasGroup.alpha = 0f;
		wheelObject.transform.localScale = Vector3.one * configuredScale * 0.94f;
		canvasObject.SetActive(true);
	}

	internal void SetWorldCenter(Vector3 worldCenter)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: 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_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)canvasObject == (Object)null || !canvasObject.activeSelf || (Object)(object)canvasRect == (Object)null || (Object)(object)wheelRect == (Object)null)
		{
			return;
		}
		Camera val = GameCameras.SilentInstance?.mainCamera ?? Camera.main;
		if (!((Object)(object)val == (Object)null))
		{
			Vector3 val2 = val.WorldToScreenPoint(worldCenter);
			Vector2 anchoredPosition = default(Vector2);
			if (!(val2.z <= 0f) && RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, Vector2.op_Implicit(val2), (Camera)null, ref anchoredPosition))
			{
				wheelRect.anchoredPosition = anchoredPosition;
			}
		}
	}

	internal void SetSelection(int selectedIndex, int equippedIndex, bool hasAimed)
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: 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_00eb: 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_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		if (entries.Count != 0 && selectedIndex >= 0 && selectedIndex < entries.Count)
		{
			ringGraphic.Configure(entries, selectedIndex, equippedIndex, hasAimed);
			for (int i = 0; i < iconRoots.Count; i++)
			{
				bool flag = hasAimed && i == selectedIndex;
				bool flag2 = i == equippedIndex;
				bool isOwned = entries[i].IsOwned;
				iconRoots[i].transform.localScale = Vector3.one * (flag ? (isOwned ? 1.08f : 1.03f) : 1f);
				((Behaviour)iconImages[i]).enabled = (Object)(object)iconImages[i].sprite != (Object)null;
				((Graphic)iconImages[i]).color = ((!isOwned) ? (flag ? LockedHoveredIcon : LockedIcon) : (flag ? SelectedIcon : (flag2 ? EquippedIcon : NormalIcon)));
			}
		}
	}

	internal void SetOpenProgress(float progress)
	{
		//IL_0049: 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_0069: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)canvasObject == (Object)null) && canvasObject.activeSelf)
		{
			float num = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(progress));
			canvasGroup.alpha = num;
			wheelObject.transform.localScale = Vector3.one * configuredScale * Mathf.Lerp(0.94f, 1f, num);
		}
	}

	internal void Hide()
	{
		if ((Object)(object)canvasObject != (Object)null)
		{
			canvasObject.SetActive(false);
		}
	}

	public void Dispose()
	{
		if ((Object)(object)canvasObject != (Object)null)
		{
			Object.Destroy((Object)(object)canvasObject);
			canvasObject = null;
		}
	}

	private void EnsureCanvas()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Expected O, but got Unknown
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Expected O, but got Unknown
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)canvasObject != (Object)null))
		{
			canvasObject = new GameObject("CrestWheel.Canvas", new Type[4]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler),
				typeof(CanvasGroup)
			});
			Object.DontDestroyOnLoad((Object)(object)canvasObject);
			canvasRect = canvasObject.GetComponent<RectTransform>();
			Canvas component = canvasObject.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 32000;
			CanvasScaler component2 = canvasObject.GetComponent<CanvasScaler>();
			component2.uiScaleMode = (ScaleMode)1;
			component2.referenceResolution = new Vector2(1920f, 1080f);
			component2.screenMatchMode = (ScreenMatchMode)0;
			component2.matchWidthOrHeight = 0.5f;
			canvasGroup = canvasObject.GetComponent<CanvasGroup>();
			canvasGroup.interactable = false;
			canvasGroup.blocksRaycasts = false;
			dimImage = CreateImage("Dim", canvasObject.transform, null);
			StretchToParent(((Graphic)dimImage).rectTransform);
			wheelObject = new GameObject("Wheel", new Type[1] { typeof(RectTransform) });
			wheelRect = wheelObject.GetComponent<RectTransform>();
			((Transform)wheelRect).SetParent(canvasObject.transform, false);
			wheelRect.anchorMin = new Vector2(0.5f, 0.5f);
			wheelRect.anchorMax = new Vector2(0.5f, 0.5f);
			wheelRect.pivot = new Vector2(0.5f, 0.5f);
			wheelRect.sizeDelta = new Vector2(480f, 480f);
			wheelRect.anchoredPosition = Vector2.zero;
			GameObject val = new GameObject("Segments", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(RadialRingGraphic)
			});
			RectTransform component3 = val.GetComponent<RectTransform>();
			((Transform)component3).SetParent((Transform)(object)wheelRect, false);
			component3.anchorMin = new Vector2(0.5f, 0.5f);
			component3.anchorMax = new Vector2(0.5f, 0.5f);
			component3.pivot = new Vector2(0.5f, 0.5f);
			component3.sizeDelta = new Vector2(440f, 440f);
			component3.anchoredPosition = Vector2.zero;
			ringGraphic = val.GetComponent<RadialRingGraphic>();
			((Graphic)ringGraphic).raycastTarget = false;
			canvasObject.SetActive(false);
		}
	}

	private void BuildIcons()
	{
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Expected O, but got Unknown
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: 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_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < iconRoots.Count; i++)
		{
			if ((Object)(object)iconRoots[i] != (Object)null)
			{
				iconRoots[i].SetActive(false);
				Object.Destroy((Object)(object)iconRoots[i]);
			}
		}
		iconRoots.Clear();
		iconImages.Clear();
		int count = entries.Count;
		if (count != 0)
		{
			float num = 176f;
			float num2 = Mathf.Clamp(MathF.PI * 2f * num / (float)count * 0.34f, 42f, 60f);
			RectTransform component = wheelObject.GetComponent<RectTransform>();
			Vector2 anchoredPosition = default(Vector2);
			for (int j = 0; j < count; j++)
			{
				float num3 = (90f - (float)j * (360f / (float)count)) * (MathF.PI / 180f);
				((Vector2)(ref anchoredPosition))..ctor(Mathf.Cos(num3) * num, Mathf.Sin(num3) * num);
				GameObject val = new GameObject("Crest " + entries[j].InternalName, new Type[1] { typeof(RectTransform) });
				RectTransform component2 = val.GetComponent<RectTransform>();
				((Transform)component2).SetParent((Transform)(object)component, false);
				component2.anchorMin = new Vector2(0.5f, 0.5f);
				component2.anchorMax = new Vector2(0.5f, 0.5f);
				component2.pivot = new Vector2(0.5f, 0.5f);
				component2.sizeDelta = new Vector2(num2 + 8f, num2 + 8f);
				component2.anchoredPosition = anchoredPosition;
				Image val2 = CreateImage("Icon", (Transform)(object)component2, entries[j].Sprite);
				SetCenteredRect(((Graphic)val2).rectTransform, num2, num2, Vector2.zero);
				val2.preserveAspect = true;
				((Behaviour)val2).enabled = (Object)(object)val2.sprite != (Object)null;
				iconRoots.Add(val);
				iconImages.Add(val2);
			}
		}
	}

	private static Image CreateImage(string name, Transform parent, Sprite sprite)
	{
		//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)
		GameObject val = new GameObject(name, new Type[3]
		{
			typeof(RectTransform),
			typeof(CanvasRenderer),
			typeof(Image)
		});
		((Transform)val.GetComponent<RectTransform>()).SetParent(parent, false);
		Image component = val.GetComponent<Image>();
		component.sprite = sprite;
		((Graphic)component).raycastTarget = false;
		return component;
	}

	private static void StretchToParent(RectTransform rect)
	{
		//IL_0001: 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_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		rect.anchorMin = Vector2.zero;
		rect.anchorMax = Vector2.one;
		rect.offsetMin = Vector2.zero;
		rect.offsetMax = Vector2.zero;
	}

	private static void SetCenteredRect(RectTransform rect, float width, float height, Vector2 position)
	{
		//IL_000b: 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_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		rect.anchorMin = new Vector2(0.5f, 0.5f);
		rect.anchorMax = new Vector2(0.5f, 0.5f);
		rect.pivot = new Vector2(0.5f, 0.5f);
		rect.sizeDelta = new Vector2(width, height);
		rect.anchoredPosition = position;
	}
}
public sealed class RadialRingGraphic : MaskableGraphic
{
	private int segmentCount;

	private int selectedIndex;

	private int equippedIndex;

	private bool hasSelection;

	private bool[] ownedSlots = Array.Empty<bool>();

	internal void Configure(IReadOnlyList<CrestEntry> entries, int selected, int equipped, bool selectionActive)
	{
		segmentCount = entries?.Count ?? 0;
		selectedIndex = selected;
		equippedIndex = equipped;
		hasSelection = selectionActive;
		if (ownedSlots.Length != segmentCount)
		{
			ownedSlots = new bool[segmentCount];
		}
		for (int i = 0; i < segmentCount; i++)
		{
			ownedSlots[i] = entries[i].IsOwned;
		}
		((Graphic)this).SetVerticesDirty();
	}

	protected override void OnPopulateMesh(VertexHelper vertexHelper)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: 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_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: 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)
		vertexHelper.Clear();
		if (segmentCount <= 0)
		{
			return;
		}
		Rect pixelAdjustedRect = ((Graphic)this).GetPixelAdjustedRect();
		Vector2 center = ((Rect)(ref pixelAdjustedRect)).center;
		float num = Mathf.Min(((Rect)(ref pixelAdjustedRect)).width, ((Rect)(ref pixelAdjustedRect)).height) * 0.47f;
		float num2 = num - 62f;
		float num3 = 360f / (float)segmentCount;
		float num4 = Mathf.Min(1.25f, num3 * 0.035f);
		int curveSteps = Mathf.Clamp(Mathf.CeilToInt(num3 / 3.5f), 8, 64);
		for (int i = 0; i < segmentCount; i++)
		{
			bool flag = i < ownedSlots.Length && ownedSlots[i];
			bool flag2 = hasSelection && i == selectedIndex;
			bool num5 = i == equippedIndex;
			Color32 color = Color32.op_Implicit(flag ? (flag2 ? new Color(0.25f, 0.055f, 0.075f, 0.9f) : new Color(0.035f, 0.032f, 0.04f, 0.8f)) : (flag2 ? new Color(0.065f, 0.065f, 0.075f, 0.62f) : new Color(0.018f, 0.018f, 0.023f, 0.46f)));
			float num6 = 90f - (float)i * num3;
			float startDegrees = num6 - num3 * 0.5f + num4 * 0.5f;
			float endDegrees = num6 + num3 * 0.5f - num4 * 0.5f;
			AddArcStrip(vertexHelper, center, num2, num, startDegrees, endDegrees, curveSteps, color);
			if (num5 && flag)
			{
				float num7 = Mathf.Min(22f, num3 * 0.28f);
				int curveSteps2 = Mathf.Clamp(Mathf.CeilToInt(num7 / 2.5f), 4, 12);
				AddArcStrip(vertexHelper, center, num2 + 3f, num2 + 7f, num6 - num7 * 0.5f, num6 + num7 * 0.5f, curveSteps2, Color32.op_Implicit(new Color(0.76f, 0.68f, 0.52f, 0.92f)));
			}
		}
	}

	private static void AddArcStrip(VertexHelper vertexHelper, Vector2 center, float innerRadius, float outerRadius, float startDegrees, float endDegrees, int curveSteps, Color32 color)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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_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_0056: 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_0061: 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_006d: 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_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: 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_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		int currentVertCount = vertexHelper.currentVertCount;
		Vector2 val = default(Vector2);
		for (int i = 0; i <= curveSteps; i++)
		{
			float num = Mathf.Lerp(startDegrees, endDegrees, (float)i / (float)curveSteps) * (MathF.PI / 180f);
			((Vector2)(ref val))..ctor(Mathf.Cos(num), Mathf.Sin(num));
			UIVertex simpleVert = UIVertex.simpleVert;
			simpleVert.color = color;
			simpleVert.position = Vector2.op_Implicit(center + val * innerRadius);
			vertexHelper.AddVert(simpleVert);
			UIVertex simpleVert2 = UIVertex.simpleVert;
			simpleVert2.color = color;
			simpleVert2.position = Vector2.op_Implicit(center + val * outerRadius);
			vertexHelper.AddVert(simpleVert2);
		}
		for (int j = 0; j < curveSteps; j++)
		{
			int num2 = currentVertCount + j * 2;
			int num3 = num2 + 1;
			int num4 = num2 + 2;
			int num5 = num2 + 3;
			vertexHelper.AddTriangle(num2, num3, num5);
			vertexHelper.AddTriangle(num2, num5, num4);
		}
	}
}
internal sealed class RandomizerCompatibility
{
	internal const string RandomizerGuid = "moriko.silksong.randomizer";

	private readonly ManualLogSource log;

	private bool initialized;

	private bool randomizerDetected;

	private bool available;

	private bool initializationWarningLogged;

	private bool invocationWarningLogged;

	private PropertyInfo saveStateInstanceProperty;

	private MethodInfo isRandomizedMethod;

	private FieldInfo receivedItemsField;

	private object crestItemType;

	private PropertyInfo cursedCrestActiveProperty;

	private MethodInfo removeUnreceivedSilkspearMethod;

	private object snapshotSaveState;

	private bool snapshotStateKnown;

	private bool snapshotCrestsRandomized;

	private HashSet<string> snapshotReceivedItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	internal RandomizerCompatibility(ManualLogSource log)
	{
		this.log = log;
	}

	internal void RefreshSnapshot()
	{
		EnsureInitialized();
		snapshotSaveState = null;
		snapshotStateKnown = false;
		snapshotCrestsRandomized = false;
		snapshotReceivedItems.Clear();
		if (!available)
		{
			return;
		}
		try
		{
			snapshotSaveState = saveStateInstanceProperty.GetValue(null);
			if (snapshotSaveState == null)
			{
				return;
			}
			snapshotCrestsRandomized = (bool)isRandomizedMethod.Invoke(snapshotSaveState, new object[1] { crestItemType });
			snapshotStateKnown = true;
			if (!snapshotCrestsRandomized || !(receivedItemsField.GetValue(snapshotSaveState) is IEnumerable enumerable))
			{
				return;
			}
			foreach (object item in enumerable)
			{
				if (item is string text && !string.IsNullOrEmpty(text))
				{
					snapshotReceivedItems.Add(text);
				}
			}
		}
		catch (Exception ex)
		{
			LogInvocationWarning("could not read crest ownership", ex);
			snapshotSaveState = null;
			snapshotStateKnown = false;
			snapshotCrestsRandomized = false;
			snapshotReceivedItems.Clear();
		}
	}

	internal bool IsCrestOwned(ToolCrest crest)
	{
		if ((Object)(object)crest == (Object)null)
		{
			return true;
		}
		string randomizerItemName = GetRandomizerItemName(crest.name);
		if (randomizerItemName == null)
		{
			return true;
		}
		if (randomizerDetected && (!available || !snapshotStateKnown))
		{
			return false;
		}
		if (!snapshotCrestsRandomized)
		{
			return true;
		}
		return snapshotReceivedItems.Contains(randomizerItemName);
	}

	internal bool IsSwitchBlocked()
	{
		EnsureInitialized();
		if (!available || cursedCrestActiveProperty == null)
		{
			return false;
		}
		try
		{
			return (bool)cursedCrestActiveProperty.GetValue(null);
		}
		catch (Exception ex)
		{
			LogInvocationWarning("could not read Cursed Crest state", ex);
			return false;
		}
	}

	internal void AfterCrestEquipped()
	{
		EnsureInitialized();
		if (!randomizerDetected || removeUnreceivedSilkspearMethod == null)
		{
			return;
		}
		try
		{
			removeUnreceivedSilkspearMethod.Invoke(null, null);
		}
		catch (Exception ex)
		{
			LogInvocationWarning("could not clean unreceived Silk Spear loadouts", ex);
		}
	}

	private void EnsureInitialized()
	{
		if (initialized || !Chainloader.PluginInfos.TryGetValue("moriko.silksong.randomizer", out var value))
		{
			return;
		}
		randomizerDetected = true;
		if ((Object)(object)((value != null) ? value.Instance : null) == (Object)null)
		{
			return;
		}
		initialized = true;
		try
		{
			Assembly assembly = ((object)value.Instance).GetType().Assembly;
			Type type = assembly.GetType("SilksongRandomizer.SaveState", throwOnError: true);
			Type type2 = assembly.GetType("SilksongRandomizer.ItemType", throwOnError: true);
			Type type3 = assembly.GetType("SilksongRandomizer.TrapManager", throwOnError: false);
			Type type4 = assembly.GetType("SilksongRandomizer.Patches.ToolPatches", throwOnError: false);
			saveStateInstanceProperty = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
			isRandomizedMethod = type.GetMethod("IsRandomized", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { type2 }, null);
			receivedItemsField = type.GetField("receivedItems", BindingFlags.Instance | BindingFlags.Public);
			crestItemType = Enum.Parse(type2, "Crest");
			cursedCrestActiveProperty = type3?.GetProperty("IsCursedCrestActive", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			removeUnreceivedSilkspearMethod = type4?.GetMethod("RemoveUnreceivedSilkspearFromCrests", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			available = saveStateInstanceProperty != null && isRandomizedMethod != null && receivedItemsField != null && crestItemType != null;
			if (available)
			{
				log.LogInfo((object)"Silksong Randomizer compatibility enabled.");
			}
			else
			{
				LogInitializationWarning("the installed randomizer did not expose the expected state members");
			}
		}
		catch (Exception ex)
		{
			available = false;
			LogInitializationWarning(ex.Message);
		}
	}

	private static string GetRandomizerItemName(string internalName)
	{
		if (string.IsNullOrEmpty(internalName))
		{
			return null;
		}
		if (internalName.StartsWith("Hunter", StringComparison.OrdinalIgnoreCase))
		{
			return "Crest: Hunter";
		}
		switch (internalName)
		{
		case "Warrior":
			return "Crest: Beast";
		case "Toolmaster":
			return "Crest: Architect";
		case "Spell":
			return "Crest: Shaman";
		case "Wanderer":
		case "Reaper":
		case "Witch":
			return "Crest: " + internalName;
		default:
			return null;
		}
	}

	private void LogInitializationWarning(string reason)
	{
		if (!initializationWarningLogged)
		{
			initializationWarningLogged = true;
			log.LogWarning((object)("Silksong Randomizer compatibility fell back to native crest state: " + reason));
		}
	}

	private void LogInvocationWarning(string operation, Exception ex)
	{
		if (!invocationWarningLogged)
		{
			invocationWarningLogged = true;
			log.LogWarning((object)("Silksong Randomizer compatibility " + operation + ": " + ex.Message));
		}
	}
}