Decompiled source of StarterSpells v1.1.0

plugins/StarterSpells.dll

Decompiled 12 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("StarterSpells")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+17c41af0f5c60e5505c351425aafe43d32ba5ec4")]
[assembly: AssemblyProduct("StarterSpells")]
[assembly: AssemblyTitle("StarterSpells")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace StarterSpells
{
	[HarmonyPatch]
	internal static class LocalWizard
	{
		private static LocalPlayer player;

		private static CharacterId? lastSelected;

		private static float nextFind;

		private static bool loggedFailure;

		internal static LocalPlayer Player
		{
			get
			{
				if ((Object)(object)player != (Object)null && !((Il2CppObjectBase)player).WasCollected)
				{
					return player;
				}
				player = null;
				try
				{
					player = SingletonPersistent<LocalPlayer>.Instance;
				}
				catch
				{
				}
				if ((Object)(object)player == (Object)null && Time.unscaledTime >= nextFind)
				{
					nextFind = Time.unscaledTime + 1f;
					try
					{
						player = Object.FindObjectOfType<LocalPlayer>();
					}
					catch
					{
					}
				}
				return player;
			}
		}

		internal static CharacterId? Current
		{
			get
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				LocalPlayer val = Player;
				if ((Object)(object)val != (Object)null)
				{
					try
					{
						return lastSelected = val.GetSelectedCharacter();
					}
					catch (Exception ex)
					{
						LogOnce("reading the selected wizard failed: " + ex.Message);
					}
				}
				if (lastSelected.HasValue)
				{
					return lastSelected;
				}
				LogOnce("the game's LocalPlayer object wasn't found yet");
				return null;
			}
		}

		private static void LogOnce(string why)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!loggedFailure)
			{
				loggedFailure = true;
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(66, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Picker can't tell which wizard is selected: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(why);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". It will keep trying.");
				}
				log.LogWarning(val);
			}
		}

		[HarmonyPatch(typeof(LocalPlayer), "SetSelectedCharacter")]
		[HarmonyPostfix]
		private static void SetSelected(LocalPlayer __instance, CharacterId character)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			player = __instance;
			lastSelected = character;
		}

		[HarmonyPatch(typeof(LocalPlayer), "LoadSelectedCharacter")]
		[HarmonyPostfix]
		private static void LoadSelected(LocalPlayer __instance)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			player = __instance;
			try
			{
				lastSelected = __instance.GetSelectedCharacter();
			}
			catch
			{
			}
		}
	}
	public class PickerUI : MonoBehaviour
	{
		private GameObject canvasGo;

		private GameObject panel;

		private TextMeshProUGUI title;

		private TextMeshProUGUI value;

		private TextMeshProUGUI hint;

		private Image icon;

		private float nextScan;

		private bool inMenu;

		private bool hidden;

		private CharacterId shownCharacter = (CharacterId)(-1);

		private string shownChoice;

		private static Action prevAction;

		private static Action nextAction;

		private static UnityAction prevUnity;

		private static UnityAction nextUnity;

		private static PickerUI instance;

		private float nextErrorLog;

		public PickerUI(IntPtr ptr)
			: base(ptr)
		{
		}//IL_0002: Unknown result type (might be due to invalid IL or missing references)


		private void Update()
		{
			instance = this;
			if (Time.unscaledTime >= nextScan)
			{
				nextScan = Time.unscaledTime + 0.5f;
				Step("menu check", delegate
				{
					bool flag = (Object)(object)Object.FindObjectOfType<MainMenuManager>() != (Object)null;
					bool flag2 = (Object)(object)Object.FindObjectOfType<RunManager>() != (Object)null;
					inMenu = flag && !flag2;
				});
			}
			bool show = inMenu && Plugin.ShowPicker.Value && !hidden;
			if (show && (Object)(object)panel == (Object)null)
			{
				Step("build", Build);
			}
			if ((Object)(object)canvasGo != (Object)null && canvasGo.activeSelf != show)
			{
				Step("show/hide", delegate
				{
					canvasGo.SetActive(show);
				});
			}
			if (inMenu)
			{
				Step("keys", HandleKeys);
			}
			if (show && (Object)(object)panel != (Object)null)
			{
				Step("refresh", delegate
				{
					Refresh(force: false);
				});
			}
		}

		private void Step(string what, Action action)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			try
			{
				action();
			}
			catch (Exception ex)
			{
				if (!(Time.unscaledTime < nextErrorLog))
				{
					nextErrorLog = Time.unscaledTime + 10f;
					ManualLogSource log = Plugin.Log;
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(11, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Picker (");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(what);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("): ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					log.LogError(val);
				}
			}
		}

		private static bool Pressed(string keyName)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null || string.IsNullOrEmpty(keyName))
			{
				return false;
			}
			if (!Enum.TryParse<Key>(keyName, ignoreCase: true, out Key result) || (int)result == 0)
			{
				return false;
			}
			KeyControl val = current[result];
			if (val != null)
			{
				return ((ButtonControl)val).wasPressedThisFrame;
			}
			return false;
		}

		private void HandleKeys()
		{
			if (Pressed(Plugin.ToggleKey.Value))
			{
				hidden = !hidden;
			}
			if (!hidden && Plugin.ShowPicker.Value)
			{
				if (Pressed(Plugin.PrevKey.Value))
				{
					Cycle(-1);
				}
				if (Pressed(Plugin.NextKey.Value))
				{
					Cycle(1);
				}
			}
		}

		private static void Cycle(int dir)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			CharacterId? val = CurrentCharacter();
			if (val.HasValue && Plugin.Choices.TryGetValue(val.Value, out var val2))
			{
				List<string> list = Spells.Options();
				int num = list.IndexOf(val2.Value);
				if (num < 0)
				{
					num = 0;
				}
				num = (num + dir + list.Count) % list.Count;
				val2.Value = list[num];
				instance?.Refresh(force: true);
			}
		}

		private static CharacterId? CurrentCharacter()
		{
			return LocalWizard.Current;
		}

		private void Refresh(bool force)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00f3: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Expected O, but got Unknown
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)panel == (Object)null)
			{
				return;
			}
			CharacterId? val = CurrentCharacter();
			if (!val.HasValue || !Plugin.Choices.TryGetValue(val.Value, out var val2))
			{
				if (!(shownChoice == "<none>") || force)
				{
					shownChoice = "<none>";
					shownCharacter = (CharacterId)(-1);
					((TMP_Text)title).text = "STARTING SPELL";
					((TMP_Text)value).text = "Pick a wizard first";
					((Graphic)value).color = new Color(1f, 1f, 1f, 0.7f);
					SetIcon(null, dimmed: false);
					Plugin.Log.LogInfo((object)"Picker: no wizard selected yet.");
				}
				return;
			}
			string text = val2.Value;
			if (force || val.Value != shownCharacter || !(text == shownChoice))
			{
				shownCharacter = val.Value;
				shownChoice = text;
				((TMP_Text)title).text = "STARTING SPELL  -  " + Spells.WizardName(val.Value);
				SpellType? val3 = Spells.ChoiceFor(val.Value);
				SpellType result;
				if (val3.HasValue)
				{
					((TMP_Text)value).text = Spells.SpellName(val3.Value);
					((Graphic)value).color = new Color(1f, 0.85f, 0.35f);
					SetIcon(val3.Value, dimmed: false);
				}
				else if (text != "Default" && Enum.TryParse<SpellType>(text, out result))
				{
					((TMP_Text)value).text = Spells.SpellName(result) + " (locked)";
					((Graphic)value).color = new Color(1f, 1f, 1f, 0.6f);
					SetIcon(result, dimmed: true);
				}
				else
				{
					SpellType? spell = Spells.NormalSpellFor(val.Value);
					((TMP_Text)value).text = (spell.HasValue ? ("Default (" + Spells.SpellName(spell.Value) + ")") : "Default");
					((Graphic)value).color = Color.white;
					SetIcon(spell, dimmed: false);
				}
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(11, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Picker: ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((TMP_Text)title).text);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" | ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((TMP_Text)value).text);
				}
				log.LogInfo(val4);
			}
		}

		private void SetIcon(SpellType? spell, bool dimmed)
		{
			//IL_001d: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)icon == (Object)null))
			{
				Sprite val = (spell.HasValue ? Spells.Icon(spell.Value) : null);
				icon.sprite = val;
				((Behaviour)icon).enabled = (Object)(object)val != (Object)null;
				((Graphic)icon).color = (Color)(dimmed ? new Color(0.45f, 0.45f, 0.45f, 0.8f) : Color.white);
			}
		}

		private void Build()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: 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_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			TMP_FontAsset val = null;
			TextMeshProUGUI val2 = Object.FindObjectOfType<TextMeshProUGUI>();
			if ((Object)(object)val2 != (Object)null)
			{
				val = ((TMP_Text)val2).font;
			}
			if ((Object)(object)val == (Object)null)
			{
				val = TMP_Settings.defaultFontAsset;
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			canvasGo = new GameObject("StarterSpells_Canvas");
			Object.DontDestroyOnLoad((Object)(object)canvasGo);
			Canvas obj = canvasGo.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 500;
			CanvasScaler obj2 = canvasGo.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			obj2.matchWidthOrHeight = 0.5f;
			canvasGo.AddComponent<GraphicRaycaster>();
			panel = NewRect("Panel", canvasGo.transform);
			((Graphic)panel.AddComponent<Image>()).color = new Color(0.08f, 0.05f, 0.14f, 0.85f);
			RectTransform component = panel.GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(600f, 150f);
			Anchor(component, Plugin.PickerPosition.Value);
			title = NewText("Title", panel.transform, val, 20f, new Vector2(0f, 46f), new Vector2(580f, 40f));
			((Graphic)title).color = new Color(0.75f, 0.7f, 0.95f);
			GameObject val3 = NewRect("Icon", panel.transform);
			RectTransform component2 = val3.GetComponent<RectTransform>();
			component2.anchoredPosition = new Vector2(-160f, 2f);
			component2.sizeDelta = new Vector2(64f, 64f);
			icon = val3.AddComponent<Image>();
			icon.preserveAspect = true;
			((Graphic)icon).raycastTarget = false;
			((Behaviour)icon).enabled = false;
			value = NewText("Value", panel.transform, val, 30f, new Vector2(38f, 2f), new Vector2(320f, 56f));
			((TMP_Text)value).enableAutoSizing = true;
			((TMP_Text)value).fontSizeMin = 18f;
			((TMP_Text)value).fontSizeMax = 30f;
			hint = NewText("Hint", panel.transform, val, 15f, new Vector2(0f, -48f), new Vector2(580f, 32f));
			((Graphic)hint).color = new Color(1f, 1f, 1f, 0.5f);
			((TMP_Text)hint).text = $"{Plugin.PrevKey.Value} / {Plugin.NextKey.Value} to change  -  {Plugin.ToggleKey.Value} to hide";
			if (prevAction == null)
			{
				prevAction = delegate
				{
					Cycle(-1);
				};
			}
			if (nextAction == null)
			{
				nextAction = delegate
				{
					Cycle(1);
				};
			}
			if (prevUnity == null)
			{
				prevUnity = DelegateSupport.ConvertDelegate<UnityAction>((Delegate)prevAction);
			}
			if (nextUnity == null)
			{
				nextUnity = DelegateSupport.ConvertDelegate<UnityAction>((Delegate)nextAction);
			}
			NewButton("Prev", panel.transform, val, "<", new Vector2(-235f, 2f), prevUnity);
			NewButton("Next", panel.transform, val, ">", new Vector2(235f, 2f), nextUnity);
			Refresh(force: true);
			Plugin.Log.LogInfo((object)"Starting-spell picker ready.");
		}

		private static GameObject NewRect(string name, Transform parent)
		{
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.AddComponent<RectTransform>();
			val.transform.SetParent(parent, false);
			return val;
		}

		private static TextMeshProUGUI NewText(string name, Transform parent, TMP_FontAsset font, float size, Vector2 pos, Vector2 box)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = NewRect(name, parent);
			RectTransform component = obj.GetComponent<RectTransform>();
			component.anchoredPosition = pos;
			component.sizeDelta = box;
			TextMeshProUGUI obj2 = obj.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj2).font = font;
			((TMP_Text)obj2).fontSize = size;
			((TMP_Text)obj2).alignment = (TextAlignmentOptions)514;
			((TMP_Text)obj2).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)obj2).overflowMode = (TextOverflowModes)0;
			((Graphic)obj2).raycastTarget = false;
			((Graphic)obj2).color = Color.white;
			return obj2;
		}

		private static void NewButton(string name, Transform parent, TMP_FontAsset font, string label, Vector2 pos, UnityAction onClick)
		{
			//IL_0010: 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)
			//IL_0048: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = NewRect(name, parent);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchoredPosition = pos;
			component.sizeDelta = new Vector2(56f, 48f);
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = new Color(0.35f, 0.22f, 0.6f, 0.95f);
			Button obj = val.AddComponent<Button>();
			((Selectable)obj).targetGraphic = (Graphic)(object)val2;
			((UnityEvent)obj.onClick).AddListener(onClick);
			((TMP_Text)NewText("Label", val.transform, font, 30f, Vector2.zero, component.sizeDelta)).text = label;
		}

		private static void Anchor(RectTransform rt, string where)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00d2: 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_0076: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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)
			Vector2 val = (rt.pivot = (rt.anchorMax = (rt.anchorMin = (Vector2)(where switch
			{
				"TopLeft" => new Vector2(0f, 1f), 
				"TopRight" => new Vector2(1f, 1f), 
				"BottomLeft" => new Vector2(0f, 0f), 
				"BottomRight" => new Vector2(1f, 0f), 
				"BottomCenter" => new Vector2(0.5f, 0f), 
				_ => new Vector2(0.5f, 1f), 
			}))));
			rt.anchoredPosition = new Vector2((val.x == 0f) ? 24f : ((val.x == 1f) ? (-24f) : 0f), (val.y == 1f) ? (-24f) : 24f);
		}
	}
	[BepInPlugin("girthy_mods.StarterSpells", "StarterSpells", "1.1.0")]
	public class Plugin : BasePlugin
	{
		public const string Guid = "girthy_mods.StarterSpells";

		public const string Name = "StarterSpells";

		public const string Version = "1.1.0";

		internal static ManualLogSource Log;

		internal const string DefaultChoice = "Default";

		internal static readonly Dictionary<CharacterId, ConfigEntry<string>> Choices = new Dictionary<CharacterId, ConfigEntry<string>>();

		internal static ConfigEntry<bool> AllowLockedSpells;

		internal static ConfigEntry<bool> ShowPicker;

		internal static ConfigEntry<string> PrevKey;

		internal static ConfigEntry<string> NextKey;

		internal static ConfigEntry<string> ToggleKey;

		internal static ConfigEntry<string> PickerPosition;

		public override void Load()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Invalid comparison between Unknown and I4
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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_0112: Expected O, but got Unknown
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Expected O, but got Unknown
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Expected O, but got Unknown
			Log = ((BasePlugin)this).Log;
			List<string> list = new List<string> { "Default" };
			foreach (SpellType value in Enum.GetValues(typeof(SpellType)))
			{
				list.Add(((object)value/*cast due to .constrained prefix*/).ToString());
			}
			AcceptableValueList<string> val = new AcceptableValueList<string>(list.ToArray());
			foreach (CharacterId value2 in Enum.GetValues(typeof(CharacterId)))
			{
				if ((int)value2 != 99999)
				{
					Choices[value2] = ((BasePlugin)this).Config.Bind<string>("Starting Spells", ((object)value2/*cast due to .constrained prefix*/).ToString(), "Default", new ConfigDescription($"Starting spell for {value2}. Default = the wizard's normal spell.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
				}
			}
			AllowLockedSpells = ((BasePlugin)this).Config.Bind<bool>("General", "AllowLockedSpells", false, "Allow starting with spells you haven't unlocked yet. Off = only spells you've unlocked.");
			ShowPicker = ((BasePlugin)this).Config.Bind<bool>("Picker", "ShowPicker", true, "Show the starting-spell picker in the main menu.");
			PickerPosition = ((BasePlugin)this).Config.Bind<string>("Picker", "ScreenPosition", "BottomCenter", new ConfigDescription("Where the picker sits on screen.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[6] { "TopCenter", "TopLeft", "TopRight", "BottomLeft", "BottomRight", "BottomCenter" }), Array.Empty<object>()));
			PrevKey = ((BasePlugin)this).Config.Bind<string>("Picker", "PreviousKey", "F6", "Key for the previous spell (Unity Input System key name).");
			NextKey = ((BasePlugin)this).Config.Bind<string>("Picker", "NextKey", "F7", "Key for the next spell.");
			ToggleKey = ((BasePlugin)this).Config.Bind<string>("Picker", "ToggleKey", "F8", "Key to show or hide the picker.");
			Harmony val3 = new Harmony("girthy_mods.StarterSpells");
			val3.PatchAll(typeof(StarterPatches));
			val3.PatchAll(typeof(LocalWizard));
			((BasePlugin)this).AddComponent<PickerUI>();
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(8, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>("StarterSpells");
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>("1.1.0");
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" ready.");
			}
			log.LogInfo(val4);
		}
	}
	internal static class Spells
	{
		private static readonly Dictionary<string, string> nameCache = new Dictionary<string, string>();

		internal static SpellType? ChoiceFor(CharacterId character)
		{
			//IL_0005: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Choices.TryGetValue(character, out var value))
			{
				return null;
			}
			string value2 = value.Value;
			if (string.IsNullOrEmpty(value2) || value2 == "Default")
			{
				return null;
			}
			if (!Enum.TryParse<SpellType>(value2, out SpellType result))
			{
				return null;
			}
			if (!Plugin.AllowLockedSpells.Value && IsLocked(result))
			{
				return null;
			}
			return result;
		}

		internal static bool IsLocked(SpellType spell)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				SpellConfiguration val = SpellConfigurationRepository.Get(spell);
				return (Object)(object)val != (Object)null && val.IsLockedByProgression();
			}
			catch
			{
				return false;
			}
		}

		internal static List<string> Options()
		{
			//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)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string> { "Default" };
			foreach (SpellType value in Enum.GetValues(typeof(SpellType)))
			{
				if (Plugin.AllowLockedSpells.Value || !IsLocked(value))
				{
					list.Add(((object)value/*cast due to .constrained prefix*/).ToString());
				}
			}
			return list;
		}

		internal static SpellType? NormalSpellFor(CharacterId character)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				CharacterResource val = CharacterResourceRepository.Get(character);
				LocalPlayer player = LocalWizard.Player;
				SkinId val2 = ((player != null) ? player.GetSelectedSkin() : val.DefaultSkin);
				StarterPatches.Bypass = true;
				try
				{
					return val.GetInitialSpell(val2);
				}
				finally
				{
					StarterPatches.Bypass = false;
				}
			}
			catch
			{
				return null;
			}
		}

		internal static Sprite Icon(SpellType spell)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				SpellConfiguration obj = SpellConfigurationRepository.Get(spell);
				SpellIconContainer val = ((obj != null) ? obj.IconContainer : null);
				if (val == null)
				{
					return null;
				}
				return val.DefaultIcon ?? val.GetIcon((ElementType)0);
			}
			catch
			{
				return null;
			}
		}

		internal unsafe static string SpellName(SpellType spell)
		{
			return Localized("SpellName_" + ((object)(*(SpellType*)(&spell))/*cast due to .constrained prefix*/).ToString(), Pretty(((object)(*(SpellType*)(&spell))/*cast due to .constrained prefix*/).ToString()));
		}

		internal unsafe static string WizardName(CharacterId c)
		{
			return Localized("Character_" + ((object)(*(CharacterId*)(&c))/*cast due to .constrained prefix*/).ToString(), Pretty(((object)(*(CharacterId*)(&c))/*cast due to .constrained prefix*/).ToString()));
		}

		private static string Localized(string key, string fallback)
		{
			if (nameCache.TryGetValue(key, out var value))
			{
				return value;
			}
			string text = null;
			try
			{
				LocalizedStringDatabase stringDatabase = LocalizationSettings.StringDatabase;
				if (stringDatabase != null)
				{
					text = stringDatabase.GetLocalizedString(TableEntryReference.op_Implicit(key), (Locale)null, (FallbackBehavior)0, (Il2CppReferenceArray<Object>)null);
				}
			}
			catch
			{
			}
			int num;
			if (!string.IsNullOrWhiteSpace(text) && text != key)
			{
				num = ((!text.Contains("No translation found")) ? 1 : 0);
				if (num != 0)
				{
					nameCache[key] = text;
				}
			}
			else
			{
				num = 0;
			}
			if (num == 0)
			{
				return fallback;
			}
			return text;
		}

		private static string Pretty(string id)
		{
			if (id == "Smg")
			{
				return "SMG";
			}
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < id.Length; i++)
			{
				if (i > 0 && char.IsUpper(id[i]) && !char.IsUpper(id[i - 1]))
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(id[i]);
			}
			return stringBuilder.ToString();
		}
	}
	[HarmonyPatch]
	internal static class StarterPatches
	{
		[ThreadStatic]
		private static int context;

		[ThreadStatic]
		internal static bool Bypass;

		private static bool IsLocalOwner(NetworkBehaviour nb)
		{
			try
			{
				if (nb.IsOwner)
				{
					return true;
				}
				NetworkManager singleton = NetworkManager.Singleton;
				return (Object)(object)singleton == (Object)null || !singleton.IsListening;
			}
			catch
			{
				return false;
			}
		}

		[HarmonyPatch(typeof(CharacterResource), "GetInitialSpell")]
		[HarmonyPostfix]
		private static void GetInitialSpell_Postfix(CharacterResource __instance, ref SpellType __result)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected I4, but got Unknown
			if (context <= 0 || Bypass)
			{
				return;
			}
			try
			{
				SpellType? val = Spells.ChoiceFor(__instance.Id);
				if (val.HasValue)
				{
					__result = (SpellType)(int)val.Value;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(17, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("GetInitialSpell: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				log.LogError(val2);
			}
		}

		[HarmonyPatch(typeof(GameplayPlayerIdentity), "InitializeOnClientsRpc")]
		[HarmonyPrefix]
		private static void InitRpc_Prefix(GameplayPlayerIdentity __instance, out bool __state)
		{
			__state = IsLocalOwner((NetworkBehaviour)(object)__instance);
			if (__state)
			{
				context++;
			}
		}

		[HarmonyPatch(typeof(GameplayPlayerIdentity), "InitializeOnClientsRpc")]
		[HarmonyPostfix]
		private static void InitRpc_Postfix(GameplayPlayerIdentity __instance, bool __state)
		{
			if (__state)
			{
				context = Math.Max(0, context - 1);
				LogEquip(__instance);
			}
		}

		[HarmonyPatch(typeof(GameplayPlayerIdentity), "Initialize")]
		[HarmonyPrefix]
		private static void Init_Prefix(GameplayPlayerIdentity __instance, out bool __state)
		{
			__state = IsLocalOwner((NetworkBehaviour)(object)__instance);
			if (__state)
			{
				context++;
			}
		}

		[HarmonyPatch(typeof(GameplayPlayerIdentity), "Initialize")]
		[HarmonyPostfix]
		private static void Init_Postfix(GameplayPlayerIdentity __instance, bool __state)
		{
			if (__state)
			{
				context = Math.Max(0, context - 1);
				LogEquip(__instance);
			}
		}

		[HarmonyPatch(typeof(GameplayPlayerIdentity), "EquipInitialSpell")]
		[HarmonyPrefix]
		private static void Equip_Prefix(GameplayPlayerIdentity __instance, out bool __state)
		{
			__state = IsLocalOwner((NetworkBehaviour)(object)__instance);
			if (__state)
			{
				context++;
			}
		}

		[HarmonyPatch(typeof(GameplayPlayerIdentity), "EquipInitialSpell")]
		[HarmonyPostfix]
		private static void Equip_Postfix(bool __state)
		{
			if (__state)
			{
				context = Math.Max(0, context - 1);
			}
		}

		[HarmonyPatch(typeof(PlayerSpell), "HasLifeStealOnSpell")]
		[HarmonyPrefix]
		private static void LifeSteal_Prefix(PlayerSpell __instance, out bool __state)
		{
			__state = IsLocalOwner((NetworkBehaviour)(object)__instance);
			if (__state)
			{
				context++;
			}
		}

		[HarmonyPatch(typeof(PlayerSpell), "HasLifeStealOnSpell")]
		[HarmonyPostfix]
		private static void LifeSteal_Postfix(bool __state)
		{
			if (__state)
			{
				context = Math.Max(0, context - 1);
			}
		}

		[HarmonyPatch(typeof(StatButtonsPanel), "OnWizardButtonClicked")]
		[HarmonyPrefix]
		private static void WizardPanel_Prefix()
		{
			context++;
		}

		[HarmonyPatch(typeof(StatButtonsPanel), "OnWizardButtonClicked")]
		[HarmonyPostfix]
		private static void WizardPanel_Postfix()
		{
			context = Math.Max(0, context - 1);
		}

		private static void LogEquip(GameplayPlayerIdentity identity)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0047: 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)
			try
			{
				CharacterResource character = identity.Character;
				if ((Object)(object)character == (Object)null)
				{
					return;
				}
				SpellType? val = Spells.ChoiceFor(character.Id);
				if (val.HasValue)
				{
					ManualLogSource log = Plugin.Log;
					bool flag = default(bool);
					BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(21, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Starting spell for ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<CharacterId>(character.Id);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<SpellType>(val.Value);
					}
					log.LogInfo(val2);
				}
			}
			catch
			{
			}
		}
	}
}