Decompiled source of AtlyssArchipelago v1.3.7

AtlyssArchipelagoWIP.dll

Decompiled 2 weeks ago
#define DEBUG
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Net.WebSockets;
using System.Numerics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Archipelago.MultiClient.Net;
using Archipelago.MultiClient.Net.BounceFeatures.DeathLink;
using Archipelago.MultiClient.Net.Colors;
using Archipelago.MultiClient.Net.ConcurrentCollection;
using Archipelago.MultiClient.Net.Converters;
using Archipelago.MultiClient.Net.DataPackage;
using Archipelago.MultiClient.Net.Enums;
using Archipelago.MultiClient.Net.Exceptions;
using Archipelago.MultiClient.Net.Extensions;
using Archipelago.MultiClient.Net.Helpers;
using Archipelago.MultiClient.Net.MessageLog.Messages;
using Archipelago.MultiClient.Net.MessageLog.Parts;
using Archipelago.MultiClient.Net.Models;
using Archipelago.MultiClient.Net.Packets;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq.JsonPath;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Utilities;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace AtlyssArchipelagoWIP
{
	[HarmonyPatch(typeof(Player), "Player_OnDeath")]
	internal class PlayerDeathPatch
	{
		private static void Postfix(Player __instance)
		{
			AtlyssArchipelagoPlugin instance = AtlyssArchipelagoPlugin.Instance;
			if (instance._dlService != null && instance.cfgDeathlink.Value)
			{
				if (AtlyssArchipelagoPlugin.reactingToDeathLink > 0)
				{
					AtlyssArchipelagoPlugin.reactingToDeathLink--;
					return;
				}
				DeathLink deathLink = new DeathLink(__instance._nickname, __instance._nickname + " was defeated.");
				instance._dlService.SendDeathLink(deathLink);
			}
		}
	}
	[HarmonyPatch(typeof(ChatBehaviour), "Send_ChatMessage")]
	public static class ChatBehaviourPatch
	{
		private static bool Prefix(ChatBehaviour __instance, string _message)
		{
			try
			{
				if (!string.IsNullOrEmpty(_message) && _message.StartsWith("/"))
				{
					string[] array = new string[6] { "/release", "/collect", "/hint", "/help", "/players", "/status" };
					bool flag = false;
					string[] array2 = array;
					foreach (string value in array2)
					{
						if (_message.StartsWith(value, StringComparison.OrdinalIgnoreCase))
						{
							flag = true;
							break;
						}
					}
					if (flag)
					{
						if ((Object)(object)AtlyssArchipelagoPlugin.Instance != (Object)null)
						{
							AtlyssArchipelagoPlugin.Instance.HandleArchipelagoCommand(_message);
						}
						__instance._focusedInChat = false;
						return false;
					}
				}
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource staticLogger = AtlyssArchipelagoPlugin.StaticLogger;
				if (staticLogger != null)
				{
					staticLogger.LogError((object)("[AtlyssAP] Chat patch error: " + ex.Message));
				}
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(FriendlyNPC_Hitbox), "OnTriggerEnter")]
	public static class AngelaRudePatch
	{
		private static void Postfix(FriendlyNPC_Hitbox __instance)
		{
			try
			{
				if ((Object)(object)AtlyssArchipelagoPlugin.Instance == (Object)null || !AtlyssArchipelagoPlugin.Instance.connected)
				{
					return;
				}
				FieldInfo fieldInfo = AccessTools.Field(typeof(FriendlyNPC_Hitbox), "_achievementTag");
				if (fieldInfo == null)
				{
					return;
				}
				string text = (string)fieldInfo.GetValue(__instance);
				if (!(text != "ATLYSS_ACHIEVEMENT_11"))
				{
					ManualLogSource staticLogger = AtlyssArchipelagoPlugin.StaticLogger;
					if (staticLogger != null)
					{
						staticLogger.LogInfo((object)"[AtlyssAP] Angela 'Rude!' hitbox triggered!");
					}
					AtlyssArchipelagoPlugin.Instance.SendCheckByName("Rude!");
					AtlyssArchipelagoPlugin.Instance.SendAPChatMessage("Found <color=#FFFF00>Rude!</color>!");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource staticLogger2 = AtlyssArchipelagoPlugin.StaticLogger;
				if (staticLogger2 != null)
				{
					staticLogger2.LogError((object)("[AtlyssAP] Angela patch error: " + ex.Message));
				}
			}
		}
	}
	[HarmonyPatch(typeof(GameManager), "Locate_Item")]
	public static class LocateItemPatch
	{
		private static ScriptableItem _fallbackDummyItem = null;

		private static Sprite _customAPSprite = null;

		private static Dictionary<string, ScriptableItem> _apItemCache = new Dictionary<string, ScriptableItem>();

		private static void Postfix(string _tag, ref ScriptableItem __result)
		{
			try
			{
				if ((Object)(object)__result != (Object)null || string.IsNullOrEmpty(_tag) || !_tag.StartsWith("[AP]"))
				{
					return;
				}
				if (_apItemCache.TryGetValue(_tag, out var value))
				{
					__result = value;
					return;
				}
				string text = ExtractItemName(_tag);
				if (string.IsNullOrEmpty(text))
				{
					AtlyssArchipelagoPlugin.StaticLogger.LogWarning((object)("[AtlyssAP] Could not extract item name from: " + _tag));
					__result = GetCustomAPItem("Unknown Item");
					_apItemCache[_tag] = __result;
					return;
				}
				ScriptableItem val = FindRealItem(text);
				if ((Object)(object)val != (Object)null)
				{
					_apItemCache[_tag] = val;
					__result = val;
					AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)("[AtlyssAP] Using real item '" + val._itemName + "' icon for: " + _tag));
				}
				else
				{
					__result = GetCustomAPItem(text);
					_apItemCache[_tag] = __result;
					AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)("[AtlyssAP] Using custom AP icon for non-ATLYSS item: " + _tag));
				}
			}
			catch (Exception ex)
			{
				AtlyssArchipelagoPlugin.StaticLogger.LogError((object)("[AtlyssAP] Locate_Item patch error: " + ex.Message));
				__result = GetCustomAPItem("Unknown Item");
			}
		}

		public static string ExtractItemName(string apItemName)
		{
			string text = apItemName.Replace("[AP] ", "");
			int num = text.LastIndexOf(" (");
			if (num > 0)
			{
				return text.Substring(0, num);
			}
			return text;
		}

		private static ScriptableItem FindRealItem(string itemName)
		{
			if (!AtlyssArchipelagoPlugin.ItemNameMapping.TryGetValue(itemName, out var value))
			{
				return null;
			}
			string text = value;
			int num = value.LastIndexOf('_');
			if (num >= 0 && num < value.Length - 1)
			{
				text = value.Substring(num + 1);
			}
			ScriptableItem val = GameManager._current.Locate_Item(text);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if (text.Contains(" (") && text.EndsWith(")"))
			{
				string text2 = text[..text.LastIndexOf(" (")];
				val = GameManager._current.Locate_Item(text2);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			string text3 = text.Replace(" ", "");
			val = GameManager._current.Locate_Item(text3);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			return null;
		}

		private static ScriptableItem GetCustomAPItem(string itemName = "Archipelago Item")
		{
			ScriptableItem fallbackDummy = GetFallbackDummy();
			if ((Object)(object)fallbackDummy != (Object)null)
			{
				ScriptableItem val = Object.Instantiate<ScriptableItem>(fallbackDummy);
				val._itemName = itemName;
				Sprite val2 = LoadCustomAPSprite();
				if ((Object)(object)val2 != (Object)null)
				{
					TrySetItemIcon(val, val2);
					if ((Object)(object)_customAPSprite == (Object)null)
					{
						AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)"[AtlyssAP] Loaded custom Archipelago icon successfully!");
					}
					_customAPSprite = val2;
				}
				else
				{
					AtlyssArchipelagoPlugin.StaticLogger.LogWarning((object)"[AtlyssAP] Failed to load custom icon, using base item icon");
				}
				return val;
			}
			AtlyssArchipelagoPlugin.StaticLogger.LogError((object)"[AtlyssAP] Could not create custom AP item - no base item available");
			return null;
		}

		private static Sprite LoadCustomAPSprite()
		{
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_customAPSprite != (Object)null)
			{
				return _customAPSprite;
			}
			try
			{
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				string[] manifestResourceNames = executingAssembly.GetManifestResourceNames();
				string text = null;
				string[] array = manifestResourceNames;
				foreach (string text2 in array)
				{
					if (text2.EndsWith("Archipelago.png-256x256_q95.png"))
					{
						text = text2;
						break;
					}
				}
				if (string.IsNullOrEmpty(text))
				{
					AtlyssArchipelagoPlugin.StaticLogger.LogError((object)"[AtlyssAP] Could not find Archipelago.png-256x256_q95.png in embedded resources");
					AtlyssArchipelagoPlugin.StaticLogger.LogError((object)("[AtlyssAP] Available resources: " + string.Join(", ", manifestResourceNames)));
					return null;
				}
				using Stream stream = executingAssembly.GetManifestResourceStream(text);
				if (stream == null)
				{
					AtlyssArchipelagoPlugin.StaticLogger.LogError((object)"[AtlyssAP] Failed to open embedded resource stream");
					return null;
				}
				byte[] array2 = new byte[stream.Length];
				stream.Read(array2, 0, array2.Length);
				Texture2D val = new Texture2D(2, 2);
				if (!ImageConversion.LoadImage(val, array2))
				{
					AtlyssArchipelagoPlugin.StaticLogger.LogError((object)"[AtlyssAP] Failed to load image data into texture");
					return null;
				}
				Sprite result = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)$"[AtlyssAP] Successfully loaded custom AP sprite: {((Texture)val).width}x{((Texture)val).height}");
				return result;
			}
			catch (Exception ex)
			{
				AtlyssArchipelagoPlugin.StaticLogger.LogError((object)("[AtlyssAP] Error loading custom sprite: " + ex.Message));
				return null;
			}
		}

		private static void TrySetItemIcon(ScriptableItem item, Sprite sprite)
		{
			try
			{
				string[] array = new string[6] { "_icon", "_itemIcon", "_sprite", "_itemSprite", "icon", "sprite" };
				Type type = ((object)item).GetType();
				string[] array2 = array;
				foreach (string text in array2)
				{
					FieldInfo field = type.GetField(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null && field.FieldType == typeof(Sprite))
					{
						field.SetValue(item, sprite);
						AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)("[AtlyssAP] Set item icon using field: " + text));
						return;
					}
				}
				AtlyssArchipelagoPlugin.StaticLogger.LogWarning((object)"[AtlyssAP] Could not find icon field on ScriptableItem");
			}
			catch (Exception ex)
			{
				AtlyssArchipelagoPlugin.StaticLogger.LogError((object)("[AtlyssAP] Error setting item icon: " + ex.Message));
			}
		}

		private static ScriptableItem GetFallbackDummy()
		{
			if ((Object)(object)_fallbackDummyItem == (Object)null)
			{
				_fallbackDummyItem = GameManager._current.Locate_Item("Bunbag");
				if ((Object)(object)_fallbackDummyItem == (Object)null)
				{
					_fallbackDummyItem = GameManager._current.Locate_Item("Wood Sword");
				}
				if ((Object)(object)_fallbackDummyItem == (Object)null)
				{
					_fallbackDummyItem = GameManager._current.Locate_Item("Leather Top");
				}
			}
			return _fallbackDummyItem;
		}
	}
	[HarmonyPatch(typeof(SettingsManager), "Close_SettingsMenu")]
	internal class SettingsMenuClosePatch
	{
		private static void Prefix(SettingsManager __instance)
		{
			if (Object.op_Implicit((Object)(object)GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_dolly_apSettingsTab")))
			{
				AtlyssArchipelagoPlugin instance = AtlyssArchipelagoPlugin.Instance;
				Toggle component = GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_dolly_apSettingsTab/_backdrop_gameTab/Scroll View_gameTab/Viewport_gameTab/Content_gameTab/_cell_fadeGameFeed/Toggle_fadeGameFeed").GetComponent<Toggle>();
				if (component.isOn != instance.cfgDeathlink.Value)
				{
					instance.ToggleDeathLink(component.isOn);
				}
				instance.cfgDeathlink.Value = component.isOn;
			}
		}
	}
	[HarmonyPatch(typeof(SettingsManager), "Open_SettingsMenu")]
	internal class SettingsMenuOpenPatch
	{
		private static void Prefix(SettingsManager __instance)
		{
			//IL_0024: 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_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_043f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0557: Unknown result type (might be due to invalid IL or missing references)
			//IL_0561: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_dolly_apSettingsTab")))
			{
				return;
			}
			Scene sceneByName = SceneManager.GetSceneByName("01_rootScene");
			if (((Scene)(ref sceneByName)).isLoaded)
			{
				bool flag = false;
				if (!Object.op_Implicit((Object)(object)GameObject.Find("_GameUI_MainMenu")))
				{
					flag = true;
					((Component)((Component)MainMenuManager._current).gameObject.transform.parent).gameObject.SetActive(true);
				}
				AtlyssArchipelagoPlugin instance = AtlyssArchipelagoPlugin.Instance;
				GameObject val = Object.Instantiate<GameObject>(GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_dolly_gameSettings"));
				((Object)val).name = "_dolly_apSettingsTab";
				val.transform.SetParent(GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu").transform, false);
				Transform val2 = val.transform.Find("_backdrop_gameTab/Scroll View_gameTab/Viewport_gameTab/Content_gameTab");
				((Component)((Component)val2).transform.Find("_header_gameSettings/Text")).GetComponent<Text>().text = "Archipelago Settings";
				Transform child = ((Component)val2).transform.GetChild(1);
				Transform child2 = ((Component)val2).transform.GetChild(2);
				Transform child3 = ((Component)val2).transform.GetChild(3);
				Transform child4 = ((Component)val2).transform.GetChild(21);
				((Component)child4).GetComponentInChildren<Text>().text = "DeathLink";
				((Component)child4).GetComponent<SettingsCell>()._setToggle = null;
				Object.Destroy((Object)(object)((Component)child).transform.GetChild(1));
				Object.Destroy((Object)(object)((Component)child2).transform.GetChild(1));
				Object.Destroy((Object)(object)((Component)child3).transform.GetChild(1));
				((Component)child).GetComponentInChildren<Text>().text = "Archipelago Server";
				((Component)child2).GetComponentInChildren<Text>().text = "Slot Name";
				((Component)child3).GetComponentInChildren<Text>().text = "Password";
				((Component)((Component)val2).transform.Find("_header_nametagSettings/Text")).GetComponent<Text>().text = "Press F5 at any time to connect!";
				for (int num = val2.childCount - 3; num >= 5; num--)
				{
					GameObject gameObject = ((Component)val2.GetChild(num)).gameObject;
					Object.Destroy((Object)(object)gameObject);
				}
				Transform val3 = Object.Instantiate<Transform>(GameObject.Find("_GameUI_MainMenu").transform.Find("_characterSelectMenu/Canvas_characterSelect/_dolly_characterManagement/_input_@nickname"));
				((Object)val3).name = "Input_apServer";
				Transform val4 = Object.Instantiate<Transform>(GameObject.Find("_GameUI_MainMenu").transform.Find("_characterSelectMenu/Canvas_characterSelect/_dolly_characterManagement/_input_@nickname"));
				((Object)val4).name = "Input_apSlot";
				Transform val5 = Object.Instantiate<Transform>(GameObject.Find("_GameUI_MainMenu").transform.Find("_characterSelectMenu/Canvas_characterSelect/_dolly_characterManagement/_input_@nickname"));
				((Object)val5).name = "Input_apPassword";
				((Component)val3).gameObject.SetActive(true);
				((Component)val4).gameObject.SetActive(true);
				((Component)val5).gameObject.SetActive(true);
				Object.Destroy((Object)(object)((Component)val3).transform.Find("_backdrop_globalNicknameTooltip"));
				Object.Destroy((Object)(object)((Component)val4).transform.Find("_backdrop_globalNicknameTooltip"));
				Object.Destroy((Object)(object)((Component)val5).transform.Find("_backdrop_globalNicknameTooltip"));
				((Component)val3).transform.SetParent(((Component)child).transform, false);
				((Component)val4).transform.SetParent(((Component)child2).transform, false);
				((Component)val5).transform.SetParent(((Component)child3).transform, false);
				((Component)val3).transform.localPosition = new Vector3(180f, 0f, 0f);
				((Component)val4).transform.localPosition = new Vector3(180f, 0f, 0f);
				((Component)val5).transform.localPosition = new Vector3(180f, 0f, 0f);
				instance.apServer = ((Component)val3).GetComponent<InputField>();
				instance.apSlot = ((Component)val4).GetComponent<InputField>();
				instance.apPassword = ((Component)val5).GetComponent<InputField>();
				instance.apDeathlink = ((Component)((Component)child4).transform.Find("Toggle_fadeGameFeed")).gameObject.GetComponent<Toggle>();
				((Text)instance.apServer.placeholder).text = "archipelago.gg:38281";
				((Text)instance.apSlot.placeholder).text = "ATLYSSPlayer";
				((Text)instance.apPassword.placeholder).text = "supersecret";
				instance.apServer.text = instance.cfgServer.Value;
				instance.apSlot.text = instance.cfgSlot.Value;
				instance.apPassword.text = instance.cfgPassword.Value;
				instance.apDeathlink.isOn = instance.cfgDeathlink.Value;
				GameObject val6 = Object.Instantiate<GameObject>(GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_dolly_tabButtons/Button_gameTab"));
				((Object)val6).name = "Button_apTab";
				val6.GetComponentInChildren<Text>().text = "Archipelago";
				GameObject val7 = GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_dolly_tabButtons");
				val6.transform.SetParent(val7.transform, false);
				((HorizontalOrVerticalLayoutGroup)val7.GetComponent<HorizontalLayoutGroup>()).childScaleWidth = true;
				((HorizontalOrVerticalLayoutGroup)val7.GetComponent<HorizontalLayoutGroup>()).childControlWidth = true;
				((LayoutGroup)val7.GetComponent<HorizontalLayoutGroup>()).padding.right = 8;
				val7.SetActive(false);
				instance.ReenableSettingsTabs();
				((UnityEvent)val6.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
				{
					__instance.Set_SettingMenuSelectionIndex(4);
				});
				if (flag)
				{
					((Component)((Component)MainMenuManager._current).gameObject.transform.parent).gameObject.SetActive(false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(SettingsManager), "Set_SettingMenuSelectionIndex")]
	internal class SettingsMenuTabsPatch
	{
		private static void Postfix(SettingsManager __instance, int _index)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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)
			Scene sceneByName = SceneManager.GetSceneByName("01_rootScene");
			if (((Scene)(ref sceneByName)).isLoaded)
			{
				if (_index == 4)
				{
					MenuElement component = GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_dolly_apSettingsTab").GetComponent<MenuElement>();
					RectTransform component2 = GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_dolly_apSettingsTab/_backdrop_gameTab/Scroll View_gameTab/Viewport_gameTab/Content_gameTab").GetComponent<RectTransform>();
					GameObject val = GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_selectHighlight_tabButtons");
					component.isEnabled = true;
					component2.anchoredPosition = Vector2.zero;
					val.transform.position = GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_dolly_tabButtons/Button_apTab").transform.position;
				}
				else
				{
					MenuElement component3 = GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_dolly_apSettingsTab").GetComponent<MenuElement>();
					component3.isEnabled = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(NetNPC), "Init_ShopkeepListing")]
	public static class ShopInventoryPatch
	{
		private static void Postfix(NetNPC __instance)
		{
			try
			{
				if (!AtlyssArchipelagoPlugin.Instance.connected || AtlyssArchipelagoPlugin.Instance._shopSanity == null || !AtlyssArchipelagoPlugin.Instance._shopSanity.IsInitialized)
				{
					return;
				}
				string name = ((Object)((Component)__instance).gameObject).name;
				string[] array = new string[12]
				{
					"_npc_Sally", "_npc_Skrit", "_npc_sallyWorker_frankie_01", "_npc_Craig", "_npc_dyeMerchant", "_npc_Tesh", "_npc_Nesh", "_npc_Rikko", "_npc_Cotoo", "_npc_Ruka",
					"_npc_fisher", "_npc_madStatue"
				};
				bool flag = false;
				string[] array2 = array;
				foreach (string text in array2)
				{
					if (name == text)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					return;
				}
				AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)("[AtlyssAP] AP merchant shop opened: " + name + " - injecting items"));
				AtlyssArchipelagoPlugin.Instance._shopSanity.InjectAPShopItems(__instance);
				try
				{
					ShopkeepManager current = ShopkeepManager._current;
					if (!((Object)(object)current != (Object)null))
					{
						return;
					}
					MethodInfo method = typeof(ShopkeepManager).GetMethod("Begin_ShopkeepListing", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (method != null)
					{
						ParameterInfo[] parameters = method.GetParameters();
						if (parameters.Length == 1)
						{
							method.Invoke(current, new object[1] { __instance });
							AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)"[AtlyssAP] Refreshed shop display via Begin_ShopkeepListing(npc)");
						}
						else if (parameters.Length == 0)
						{
							method.Invoke(current, null);
							AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)"[AtlyssAP] Refreshed shop display via Begin_ShopkeepListing()");
						}
						return;
					}
					string[] array3 = new string[6] { "Refresh_ShopListing", "Init_ShopListing", "Update_ShopListing", "Build_ShopListing", "Begin_ShopListing", "Set_ShopListing" };
					string[] array4 = array3;
					foreach (string text2 in array4)
					{
						MethodInfo method2 = typeof(ShopkeepManager).GetMethod(text2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						if (method2 != null)
						{
							ParameterInfo[] parameters2 = method2.GetParameters();
							if (parameters2.Length == 1 && parameters2[0].ParameterType == typeof(NetNPC))
							{
								method2.Invoke(current, new object[1] { __instance });
								AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)("[AtlyssAP] Refreshed shop display via " + text2 + "(npc)"));
								break;
							}
							if (parameters2.Length == 0)
							{
								method2.Invoke(current, null);
								AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)("[AtlyssAP] Refreshed shop display via " + text2 + "()"));
								break;
							}
						}
					}
				}
				catch (Exception ex)
				{
					AtlyssArchipelagoPlugin.StaticLogger.LogWarning((object)("[AtlyssAP] Could not refresh shop display: " + ex.Message));
				}
			}
			catch (Exception ex2)
			{
				AtlyssArchipelagoPlugin.StaticLogger.LogError((object)("[AtlyssAP] Shop patch error: " + ex2.Message));
				AtlyssArchipelagoPlugin.StaticLogger.LogError((object)("[AtlyssAP] Stack trace: " + ex2.StackTrace));
			}
		}
	}
	[HarmonyPatch(typeof(ShopkeepManager), "Init_PurchaseItem")]
	public static class ShopPurchasePatch
	{
		private static bool Prefix(ScriptableItem _scriptableItem, int _quantity, string _key, ShopListDataEntry _setEntry)
		{
			try
			{
				if (!AtlyssArchipelagoPlugin.Instance.connected)
				{
					return true;
				}
				if (AtlyssArchipelagoPlugin.Instance._shopSanity == null)
				{
					return true;
				}
				if (!AtlyssArchipelagoPlugin.Instance._shopSanity.IsInitialized)
				{
					return true;
				}
				string itemName = _setEntry._shopStruct._itemName;
				if (!itemName.StartsWith("[AP]"))
				{
					return true;
				}
				AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)("[AtlyssAP] Intercepting purchase of: " + itemName));
				Player mainPlayer = Player._mainPlayer;
				if ((Object)(object)mainPlayer == (Object)null)
				{
					AtlyssArchipelagoPlugin.StaticLogger.LogError((object)"[AtlyssAP] Player not found for purchase!");
					return false;
				}
				PlayerInventory component = ((Component)mainPlayer).GetComponent<PlayerInventory>();
				if ((Object)(object)component == (Object)null)
				{
					AtlyssArchipelagoPlugin.StaticLogger.LogError((object)"[AtlyssAP] PlayerInventory not found!");
					return false;
				}
				int num = _setEntry._shopStruct._dedicatedValue;
				if (_setEntry._shopStruct._useDedicatedValue)
				{
					num = _setEntry._shopStruct._dedicatedValue;
				}
				else if ((Object)(object)_scriptableItem != (Object)null)
				{
					num = _scriptableItem._vendorCost;
				}
				if (component._heldCurrency < num)
				{
					ErrorPromptTextManager.current.Init_ErrorPrompt("Not enough Crowns");
					AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)"[AtlyssAP] Player cannot afford AP item");
					return false;
				}
				component.Network_heldCurrency -= num;
				AtlyssArchipelagoPlugin.StaticLogger.LogInfo((object)$"[AtlyssAP] Deducted {num} crowns from player");
				component.Play_PurchaseSound();
				AtlyssArchipelagoPlugin.Instance._shopSanity.HandleAPItemPurchase(itemName, _key);
				return false;
			}
			catch (Exception ex)
			{
				AtlyssArchipelagoPlugin.StaticLogger.LogError((object)("[AtlyssAP] Shop purchase patch error: " + ex.Message));
				return true;
			}
		}
	}
	public class SpikePatch
	{
		[HarmonyPatch(typeof(File), "ReadAllText", new Type[] { typeof(string) })]
		public static class File_ReadAllText_Patch
		{
			private static bool Prefix(ref string path, ref string __result)
			{
				try
				{
					if (!ShouldRedirect())
					{
						return true;
					}
					if (path.EndsWith("atl_itemBank") && !path.Contains("_ap"))
					{
						string aPMasterBankPath = ArchipelagoSpikeStorage.GetAPMasterBankPath();
						if (File.Exists(aPMasterBankPath))
						{
							__result = File.ReadAllText(aPMasterBankPath);
							ManualLogSource staticLogger = AtlyssArchipelagoPlugin.StaticLogger;
							if (staticLogger != null)
							{
								staticLogger.LogInfo((object)"[AtlyssAP] Redirected Spike load: MASTER bank -> AP MASTER bank");
							}
							return false;
						}
						__result = "{ \"_heldItemStorage\": [] }";
						return false;
					}
					if (path.Contains("atl_itemBank_") && !path.Contains("_ap_"))
					{
						string fileName = Path.GetFileName(path);
						for (int i = 1; i <= 7; i++)
						{
							if (!(fileName == $"atl_itemBank_{i:D2}"))
							{
								continue;
							}
							string aPBankPath = ArchipelagoSpikeStorage.GetAPBankPath(i);
							if (File.Exists(aPBankPath))
							{
								__result = File.ReadAllText(aPBankPath);
								ManualLogSource staticLogger2 = AtlyssArchipelagoPlugin.StaticLogger;
								if (staticLogger2 != null)
								{
									staticLogger2.LogInfo((object)$"[AtlyssAP] Redirected Spike load: bank {i} -> AP bank {i}");
								}
								return false;
							}
							__result = "{ \"_heldItemStorage\": [] }";
							return false;
						}
					}
					return true;
				}
				catch (Exception ex)
				{
					ManualLogSource staticLogger3 = AtlyssArchipelagoPlugin.StaticLogger;
					if (staticLogger3 != null)
					{
						staticLogger3.LogError((object)("[AtlyssAP] Error in File.ReadAllText patch: " + ex.Message));
					}
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(File), "WriteAllText", new Type[]
		{
			typeof(string),
			typeof(string)
		})]
		public static class File_WriteAllText_Patch
		{
			private static bool Prefix(ref string path, string contents)
			{
				try
				{
					if (!ShouldRedirect())
					{
						return true;
					}
					if (path.EndsWith("atl_itemBank") && !path.Contains("_ap"))
					{
						string aPMasterBankPath = ArchipelagoSpikeStorage.GetAPMasterBankPath();
						string directoryName = Path.GetDirectoryName(aPMasterBankPath);
						if (!Directory.Exists(directoryName))
						{
							Directory.CreateDirectory(directoryName);
						}
						File.WriteAllText(aPMasterBankPath, contents);
						ManualLogSource staticLogger = AtlyssArchipelagoPlugin.StaticLogger;
						if (staticLogger != null)
						{
							staticLogger.LogInfo((object)"[AtlyssAP] Redirected Spike save: MASTER bank -> AP MASTER bank");
						}
						return false;
					}
					if (path.Contains("atl_itemBank_") && !path.Contains("_ap_"))
					{
						string fileName = Path.GetFileName(path);
						for (int i = 1; i <= 7; i++)
						{
							if (fileName == $"atl_itemBank_{i:D2}")
							{
								string aPBankPath = ArchipelagoSpikeStorage.GetAPBankPath(i);
								File.WriteAllText(aPBankPath, contents);
								ManualLogSource staticLogger2 = AtlyssArchipelagoPlugin.StaticLogger;
								if (staticLogger2 != null)
								{
									staticLogger2.LogInfo((object)$"[AtlyssAP] Redirected Spike save: bank {i} -> AP bank {i}");
								}
								return false;
							}
						}
					}
					return true;
				}
				catch (Exception ex)
				{
					ManualLogSource staticLogger3 = AtlyssArchipelagoPlugin.StaticLogger;
					if (staticLogger3 != null)
					{
						staticLogger3.LogError((object)("[AtlyssAP] Error in File.WriteAllText patch: " + ex.Message));
					}
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(ItemStorageManager), "Create_StorageEntry")]
		public static class CreateStorageEntry_SafetyPatch
		{
			private static bool Prefix(ItemStorageManager __instance, ItemData _itemData, ScriptableItem _scriptItem, int _index, int _slotNumber)
			{
				try
				{
					FieldInfo field = typeof(ItemStorageManager).GetField("_currentStorageEntries", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null && field.GetValue(__instance) is Array array && (_slotNumber < 0 || _slotNumber >= array.Length))
					{
						ManualLogSource staticLogger = AtlyssArchipelagoPlugin.StaticLogger;
						if (staticLogger != null)
						{
							staticLogger.LogWarning((object)($"[AtlyssAP] Skipping storage entry: slot {_slotNumber} out of bounds " + $"(max {array.Length}) for item '{_itemData?._itemName}'"));
						}
						return false;
					}
					return true;
				}
				catch (Exception ex)
				{
					ManualLogSource staticLogger2 = AtlyssArchipelagoPlugin.StaticLogger;
					if (staticLogger2 != null)
					{
						staticLogger2.LogError((object)("[AtlyssAP] Create_StorageEntry safety check error: " + ex.Message));
					}
					return true;
				}
			}
		}

		private static bool ShouldRedirect()
		{
			if ((Object)(object)AtlyssArchipelagoPlugin.Instance != (Object)null && AtlyssArchipelagoPlugin.Instance.connected)
			{
				return true;
			}
			if (ArchipelagoSpikeStorage.IsAPSessionActive())
			{
				return true;
			}
			return false;
		}

		public static void InitializeAPStorage()
		{
			try
			{
				ArchipelagoSpikeStorage.SetAPSessionActive();
				if (!ArchipelagoSpikeStorage.AreAPBanksInitialized())
				{
					ArchipelagoSpikeStorage.InitializeAPBanks();
					ManualLogSource staticLogger = AtlyssArchipelagoPlugin.StaticLogger;
					if (staticLogger != null)
					{
						staticLogger.LogInfo((object)"[AtlyssAP] Initialized AP Spike storage (separate from vanilla)");
					}
				}
				else
				{
					int totalItemCount = ArchipelagoSpikeStorage.GetTotalItemCount();
					ManualLogSource staticLogger2 = AtlyssArchipelagoPlugin.StaticLogger;
					if (staticLogger2 != null)
					{
						staticLogger2.LogInfo((object)$"[AtlyssAP] AP Spike storage loaded ({totalItemCount} items stored)");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource staticLogger3 = AtlyssArchipelagoPlugin.StaticLogger;
				if (staticLogger3 != null)
				{
					staticLogger3.LogError((object)("[AtlyssAP] Failed to initialize AP storage: " + ex.Message));
				}
			}
		}
	}
	[BepInPlugin("com.azrael.atlyss.ap", "Atlyss Archipelago", "1.3.1")]
	public class AtlyssArchipelagoPlugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <EnableSettingsTabs>d__134 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AtlyssArchipelagoPlugin <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EnableSettingsTabs>d__134(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForEndOfFrame();
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					GameObject.Find("_SettingsManager/Canvas_SettingsMenu/_dolly_settingsMenu/_dolly_tabButtons").SetActive(true);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private bool _goalSent = false;

		private float _lastAllQuestsCheck = 0f;

		private bool _allQuestsDiagLogged = false;

		public static readonly Dictionary<string, long> AllLocationNameToId = new Dictionary<string, long>
		{
			{ "A Warm Welcome", 1L },
			{ "Communing Catacombs", 2L },
			{ "Diva Must Die", 3L },
			{ "The Keep Within", 4L },
			{ "Tethering Grove", 5L },
			{ "The Glyphik Booklet", 6L },
			{ "Cleaning Terrace", 7L },
			{ "Ancient Beings", 8L },
			{ "Wicked Wizboars", 9L },
			{ "Spiraling In The Grove", 10L },
			{ "Hell In The Grove", 11L },
			{ "Nulversa Magica", 12L },
			{ "Finding Ammagon", 13L },
			{ "The Colossus", 14L },
			{ "Night Spirits", 15L },
			{ "Ridding Slimes", 16L },
			{ "Huntin' Hogs", 17L },
			{ "Purging the Grove", 18L },
			{ "Cleansing the Grove", 19L },
			{ "Nulversa Viscera", 20L },
			{ "Call of Fury", 21L },
			{ "Mastery of Strength", 22L },
			{ "Beckoning Foes", 23L },
			{ "Ghostly Goods", 24L },
			{ "Makin' a Mekspear", 25L },
			{ "Makin' a Wizwand", 26L },
			{ "Makin' a Vile Blade", 27L },
			{ "Makin' a Golem Chestpiece", 28L },
			{ "Makin' a Ragespear", 29L },
			{ "Makin' a Monolith Chestpiece", 30L },
			{ "Makin' a Firebreath Blade", 31L },
			{ "Makin' a Follycannon", 32L },
			{ "Summore' Spectral Powder!", 33L },
			{ "Makin' More Mekspears", 34L },
			{ "Makin' More Wizwands", 35L },
			{ "Makin' More Vile Blades", 36L },
			{ "Summore' Golem Chestpieces", 37L },
			{ "Makin' More Ragespears", 38L },
			{ "Summore' Monolith Chestpieces", 39L },
			{ "Nulversa, Greenversa!", 40L },
			{ "Summore' Firebreath Blades", 41L },
			{ "Makin' More Follycannons", 42L },
			{ "Focusin' in", 43L },
			{ "Mastery of Dexterity", 44L },
			{ "Whatta' Rush!", 45L },
			{ "The Voice of Zuulneruda", 46L },
			{ "Killing Tomb", 47L },
			{ "Purging the Undead", 48L },
			{ "Rattlecage Rage", 49L },
			{ "Consumed Madness", 50L },
			{ "Eradicating the Undead", 51L },
			{ "Reviling the Rageboars", 52L },
			{ "Gatling Galius", 53L },
			{ "Reviling more Rageboars", 54L },
			{ "Facing Foes", 55L },
			{ "The Gall of Galius", 56L },
			{ "Dense Ingots", 57L },
			{ "Amberite Ingots", 58L },
			{ "Sapphite Ingots", 59L },
			{ "Reach Level 2", 60L },
			{ "Reach Level 4", 61L },
			{ "Reach Level 6", 62L },
			{ "Reach Level 8", 63L },
			{ "Reach Level 10", 64L },
			{ "Reach Level 12", 65L },
			{ "Reach Level 14", 66L },
			{ "Reach Level 16", 67L },
			{ "Reach Level 18", 68L },
			{ "Reach Level 20", 69L },
			{ "Reach Level 22", 70L },
			{ "Reach Level 24", 71L },
			{ "Reach Level 26", 72L },
			{ "Reach Level 28", 73L },
			{ "Reach Level 30", 74L },
			{ "Reach Level 32", 75L },
			{ "Buy Item #1 from Sally's Nook", 76L },
			{ "Buy Item #2 from Sally's Nook", 77L },
			{ "Buy Item #3 from Sally's Nook", 78L },
			{ "Buy Item #4 from Sally's Nook", 79L },
			{ "Buy Item #5 from Sally's Nook", 80L },
			{ "Buy Item #1 from Skrit's Sikrit Market", 81L },
			{ "Buy Item #2 from Skrit's Sikrit Market", 82L },
			{ "Buy Item #3 from Skrit's Sikrit Market", 83L },
			{ "Buy Item #4 from Skrit's Sikrit Market", 84L },
			{ "Buy Item #5 from Skrit's Sikrit Market", 85L },
			{ "Buy Item #1 from Frankie's Goods", 86L },
			{ "Buy Item #2 from Frankie's Goods", 87L },
			{ "Buy Item #3 from Frankie's Goods", 88L },
			{ "Buy Item #4 from Frankie's Goods", 89L },
			{ "Buy Item #5 from Frankie's Goods", 90L },
			{ "Buy Item #1 from Dye Merchant", 91L },
			{ "Buy Item #2 from Dye Merchant", 92L },
			{ "Buy Item #3 from Dye Merchant", 93L },
			{ "Buy Item #4 from Dye Merchant", 94L },
			{ "Buy Item #5 from Dye Merchant", 95L },
			{ "Buy Item #1 from Tesh's Wares", 96L },
			{ "Buy Item #2 from Tesh's Wares", 97L },
			{ "Buy Item #3 from Tesh's Wares", 98L },
			{ "Buy Item #4 from Tesh's Wares", 99L },
			{ "Buy Item #5 from Tesh's Wares", 100L },
			{ "Buy Item #1 from Nesh's Wares", 101L },
			{ "Buy Item #2 from Nesh's Wares", 102L },
			{ "Buy Item #3 from Nesh's Wares", 103L },
			{ "Buy Item #4 from Nesh's Wares", 104L },
			{ "Buy Item #5 from Nesh's Wares", 105L },
			{ "Buy Item #1 from Rikko's Treasures", 106L },
			{ "Buy Item #2 from Rikko's Treasures", 107L },
			{ "Buy Item #3 from Rikko's Treasures", 108L },
			{ "Buy Item #4 from Rikko's Treasures", 109L },
			{ "Buy Item #5 from Rikko's Treasures", 110L },
			{ "Buy Item #1 from Cotoo's Treasures", 111L },
			{ "Buy Item #2 from Cotoo's Treasures", 112L },
			{ "Buy Item #3 from Cotoo's Treasures", 113L },
			{ "Buy Item #4 from Cotoo's Treasures", 114L },
			{ "Buy Item #5 from Cotoo's Treasures", 115L },
			{ "Buy Item #1 from Ruka's Furnace", 116L },
			{ "Buy Item #2 from Ruka's Furnace", 117L },
			{ "Buy Item #3 from Ruka's Furnace", 118L },
			{ "Buy Item #4 from Ruka's Furnace", 119L },
			{ "Buy Item #5 from Ruka's Furnace", 120L },
			{ "Buy Item #1 from Torta's Fishing Shack", 121L },
			{ "Buy Item #2 from Torta's Fishing Shack", 122L },
			{ "Buy Item #3 from Torta's Fishing Shack", 123L },
			{ "Buy Item #4 from Torta's Fishing Shack", 124L },
			{ "Buy Item #5 from Torta's Fishing Shack", 125L },
			{ "Buy Item #1 from Mad Statue's Gift", 126L },
			{ "Buy Item #2 from Mad Statue's Gift", 127L },
			{ "Buy Item #3 from Mad Statue's Gift", 128L },
			{ "Buy Item #4 from Mad Statue's Gift", 129L },
			{ "Buy Item #5 from Mad Statue's Gift", 130L },
			{ "Fishing Lv. 1", 131L },
			{ "Fishing Lv. 2", 132L },
			{ "Fishing Lv. 3", 133L },
			{ "Fishing Lv. 4", 134L },
			{ "Fishing Lv. 5", 135L },
			{ "Fishing Lv. 6", 136L },
			{ "Fishing Lv. 7", 137L },
			{ "Fishing Lv. 8", 138L },
			{ "Fishing Lv. 9", 139L },
			{ "Fishing Lv. 10", 140L },
			{ "Mining Lv. 1", 141L },
			{ "Mining Lv. 2", 142L },
			{ "Mining Lv. 3", 143L },
			{ "Mining Lv. 4", 144L },
			{ "Mining Lv. 5", 145L },
			{ "Mining Lv. 6", 146L },
			{ "Mining Lv. 7", 147L },
			{ "Mining Lv. 8", 148L },
			{ "Mining Lv. 9", 149L },
			{ "Mining Lv. 10", 150L },
			{ "A New Journey", 151L },
			{ "Clearing Catacombs (1-6)", 152L },
			{ "Clearing Catacombs (6-12)", 153L },
			{ "Becoming a Fighter", 154L },
			{ "Becoming a Mystic", 155L },
			{ "Becoming a Bandit", 156L },
			{ "Clearing Catacombs (12-18)", 157L },
			{ "Clearing Grove (15-20)", 158L },
			{ "Clearing Grove (20-25)", 159L },
			{ "Judgement", 160L },
			{ "Corrupted Arcana", 161L },
			{ "Holier than Thou", 162L },
			{ "Altered Vision", 163L },
			{ "Scaling the Tower", 164L },
			{ "Rude!", 165L },
			{ "Fashion Sense", 166L },
			{ "Trout Master", 167L },
			{ "Skill Student", 168L }
		};

		private static readonly Dictionary<string, long> AllQuestToLocation = new Dictionary<string, long>
		{
			{ "A Warm Welcome", 1L },
			{ "Communing Catacombs", 2L },
			{ "Diva Must Die", 3L },
			{ "The Keep Within", 4L },
			{ "Tethering Grove", 5L },
			{ "The Glyphik Booklet", 6L },
			{ "Cleaning Terrace", 7L },
			{ "Ancient Beings", 8L },
			{ "Wicked Wizboars", 9L },
			{ "Spiraling In The Grove", 10L },
			{ "Hell In The Grove", 11L },
			{ "Nulversa Magica", 12L },
			{ "Finding Ammagon", 13L },
			{ "The Colossus", 14L },
			{ "Night Spirits", 15L },
			{ "Ridding Slimes", 16L },
			{ "Huntin' Hogs", 17L },
			{ "Purging the Grove", 18L },
			{ "Cleansing the Grove", 19L },
			{ "Nulversa Viscera", 20L },
			{ "Call of Fury", 21L },
			{ "Mastery of Strength", 22L },
			{ "Beckoning Foes", 23L },
			{ "Ghostly Goods", 24L },
			{ "Makin' a Mekspear", 25L },
			{ "Makin' a Wizwand", 26L },
			{ "Makin' a Vile Blade", 27L },
			{ "Makin' a Golem Chestpiece", 28L },
			{ "Makin' a Ragespear", 29L },
			{ "Makin' a Monolith Chestpiece", 30L },
			{ "Makin' a Firebreath Blade", 31L },
			{ "Makin' a Follycannon", 32L },
			{ "Summore' Spectral Powder!", 33L },
			{ "Makin' More Mekspears", 34L },
			{ "Makin' More Wizwands", 35L },
			{ "Makin' More Vile Blades", 36L },
			{ "Summore' Golem Chestpieces", 37L },
			{ "Makin' More Ragespears", 38L },
			{ "Summore' Monolith Chestpieces", 39L },
			{ "Nulversa, Greenversa!", 40L },
			{ "Summore' Firebreath Blades", 41L },
			{ "Makin' More Follycannons", 42L },
			{ "Focusin' in", 43L },
			{ "Mastery of Dexterity", 44L },
			{ "Whatta' Rush!", 45L },
			{ "The Voice of Zuulneruda", 46L },
			{ "Killing Tomb", 47L },
			{ "Purging the Undead", 48L },
			{ "Rattlecage Rage", 49L },
			{ "Consumed Madness", 50L },
			{ "Eradicating the Undead", 51L },
			{ "Reviling the Rageboars", 52L },
			{ "Gatling Galius", 53L },
			{ "Reviling more Rageboars", 54L },
			{ "Facing Foes", 55L },
			{ "The Gall of Galius", 56L },
			{ "Dense Ingots", 57L },
			{ "Amberite Ingots", 58L },
			{ "Sapphite Ingots", 59L }
		};

		public static readonly Dictionary<string, string> ItemNameMapping = new Dictionary<string, string>
		{
			{ "Bunbag Pack", "(lv-0) STATUSCONSUMABLE_Bunbag" },
			{ "Bunjar Pack", "(lv-0) STATUSCONSUMABLE_Bunjar" },
			{ "Bunpot Pack", "(lv-0) STATUSCONSUMABLE_Bunpot" },
			{ "Regen Potion Pack", "(lv-10) STATUSCONSUMABLE_Regen Potion" },
			{ "Regen Vial Pack", "(lv-0) STATUSCONSUMABLE_Regen Vial" },
			{ "Magiclove Pack", "(lv-0) STATUSCONSUMABLE_Magiclove" },
			{ "Magiflower Pack", "(lv-0) STATUSCONSUMABLE_Magiflower" },
			{ "Magileaf Pack", "(lv-0) STATUSCONSUMABLE_Magileaf" },
			{ "Stamstar", "(lv-0) STATUSCONSUMABLE_Stamstar" },
			{ "Agility Potion Pack", "(lv-10) STATUSCONSUMABLE_Agility Potion" },
			{ "Agility Vial Pack", "(lv-0) STATUSCONSUMABLE_Agility Vial" },
			{ "Bolster Potion Pack", "(lv-10) STATUSCONSUMABLE_Bolster Potion" },
			{ "Bolster Vial Pack", "(lv-0) STATUSCONSUMABLE_Bolster Vial" },
			{ "Wisdom Potion Pack", "(lv-10) STATUSCONSUMABLE_Wisdom Potion" },
			{ "Wisdom Vial Pack", "(lv-0) STATUSCONSUMABLE_Wisdom Vial" },
			{ "Tome of Greater Experience", "(lv-0) STATUSCONSUMABLE_Tome of Greater Experience" },
			{ "Tome of Experience", "(lv-0) STATUSCONSUMABLE_Tome of Experience" },
			{ "Tome of Lesser Experience", "(lv-0) STATUSCONSUMABLE_Tome of Lesser Experience" },
			{ "Carrot Cake Pack", "(lv-0) STATUSCONSUMABLE_Carrot Cake" },
			{ "Minchroom Juice Pack", "(lv-0) STATUSCONSUMABLE_Minchroom Juice" },
			{ "Spectral Powder Pack", "(lv-0) STATUSCONSUMABLE_Spectral Powder" },
			{ "Geistlord Badge", "TRADEITEM_Geistlord Badge" },
			{ "Coldgeist Badge", "TRADEITEM_Coldgeist Badge" },
			{ "Earthcore Badge", "TRADEITEM_Earthcore Badge" },
			{ "Windcore Badge", "TRADEITEM_Windcore Badge" },
			{ "Iron Cluster", "TRADEITEM_Iron Cluster" },
			{ "Copper Cluster", "TRADEITEM_Copper Cluster" },
			{ "Mithril Cluster", "TRADEITEM_Mithril Cluster" },
			{ "Dense Ingot", "TRADEITEM_Dense Ingot" },
			{ "Sapphite Ingot", "TRADEITEM_Sapphite Ingot" },
			{ "Amberite Ingot", "TRADEITEM_Amberite Ingot" },
			{ "Soul Pearl", "TRADEITEM_Soul Pearl" },
			{ "Experience Bond", "TRADEITEM_Experience Bond" },
			{ "Crypt Blade", "(lv-2) WEAPON_Crypt Blade (Sword, Strength)" },
			{ "Femur Club", "(lv-2) WEAPON_Femur Club (Sword, Strength)" },
			{ "Ironbark Sword", "(lv-2) WEAPON_Ironbark Sword (Sword, Strength)" },
			{ "Slimecrust Blade", "(lv-2) WEAPON_Slimecrust Blade (Sword, Strength)" },
			{ "Gilded Sword", "(lv-4) WEAPON_Gilded Sword (Sword, Strength)" },
			{ "Splitbark Club", "(lv-4) WEAPON_Splitbark Club (Sword, Strength)" },
			{ "Demicrypt Blade", "(lv-6) WEAPON_Demicrypt Blade (Sword, Strength)" },
			{ "Dense Mace", "(lv-6) WEAPON_Dense Mace (Sword, Strength)" },
			{ "Iron Sword", "(lv-6) WEAPON_Iron Sword (Sword, Strength)" },
			{ "Dawn Mace", "(lv-8) WEAPON_Dawn Mace (Sword, Strength)" },
			{ "Rude Blade", "(lv-8) WEAPON_Rude Blade (Sword, Strength)" },
			{ "Vile Blade", "(lv-8) WEAPON_Vile Blade (Sword, Strength)" },
			{ "Amberite Sword", "(lv-12) WEAPON_Amberite Sword (Sword, Strength)" },
			{ "Nethercrypt Blade", "(lv-12) WEAPON_Nethercrypt Blade (Sword, Strength)" },
			{ "Coldgeist Blade", "(lv-16) WEAPON_Coldgeist Blade (Sword, Strength)" },
			{ "Mithril Sword", "(lv-16) WEAPON_Mithril Sword (Sword, Strength)" },
			{ "Serrated Blade", "(lv-16) WEAPON_Serrated Blade (Sword, Strength)" },
			{ "Nulrok Mace", "(lv-20) WEAPON_Nulrok Mace (Sword, Strength)" },
			{ "Firebreath Blade", "(lv-22) WEAPON_Firebreath Blade (Sword, Strength)" },
			{ "Valdur Blade", "(lv-24) WEAPON_Valdur Blade (Sword, Strength)" },
			{ "Fier Blade", "(lv-26) WEAPON_Fier Blade (Sword, Strength)" },
			{ "Slimek Axehammer", "(lv-4) WEAPON_Slimek Axehammer (Hammer, Strength)" },
			{ "Dense Hammer", "(lv-6) WEAPON_Dense Hammer (Hammer, Strength)" },
			{ "Iron Axehammer", "(lv-6) WEAPON_Iron Axehammer (Hammer, Strength)" },
			{ "Crypt Pounder", "(lv-8) WEAPON_Crypt Pounder (Hammer, Strength)" },
			{ "Quake Pummeler", "(lv-18) WEAPON_Quake Pummeler (Hammer, Strength)" },
			{ "Mini Geist Scythe", "(lv-4) WEAPON_Mini Geist Scythe (Greatblade, Strength)" },
			{ "Geist Scythe", "(lv-6) WEAPON_Geist Scythe (Greatblade, Strength)" },
			{ "Stone Greatblade", "(lv-8) WEAPON_Stone Greatblade (Greatblade, Strength)" },
			{ "Amberite Warstar", "(lv-12) WEAPON_Amberite Warstar (Greatblade, Strength)" },
			{ "Dolkin's Axe", "(lv-12) WEAPON_Dolkin's Axe (Greatblade, Strength)" },
			{ "Poltergeist Scythe", "(lv-14) WEAPON_Poltergeist Scythe (Greatblade, Strength)" },
			{ "Coldgeist Punisher", "(lv-16) WEAPON_Coldgeist Punisher (Greatblade, Strength)" },
			{ "Deadwood Axe", "(lv-16) WEAPON_Deadwood Axe (Greatblade, Strength)" },
			{ "Mithril Greatsword", "(lv-16) WEAPON_Mithril Greatsword (Greatblade, Strength)" },
			{ "Deathknight Runeblade", "(lv-22) WEAPON_Deathknight Runeblade (Greatblade, Strength)" },
			{ "Ryzer Greataxe", "(lv-26) WEAPON_Ryzer Greataxe (Greatblade, Strength)" },
			{ "Dense Spear", "(lv-6) WEAPON_Dense Spear (Polearm, Strength)" },
			{ "Iron Spear", "(lv-6) WEAPON_Iron Spear (Polearm, Strength)" },
			{ "Cryptsinge Halberd", "(lv-8) WEAPON_Cryptsinge Halberd (Polearm, Strength)" },
			{ "Mekspear", "(lv-8) WEAPON_Mekspear (Polearm, Strength)" },
			{ "Amberite Halberd", "(lv-12) WEAPON_Amberite Halberd (Polearm, Strength)" },
			{ "Necroroyal Halberd", "(lv-12) WEAPON_Necroroyal Halberd (Polearm, Strength)" },
			{ "Sinner Bardiche", "(lv-12) WEAPON_Sinner Bardiche (Polearm, Strength)" },
			{ "Mithril Halberd", "(lv-16) WEAPON_Mithril Halberd (Polearm, Strength)" },
			{ "Ragespear", "(lv-16) WEAPON_Ragespear (Polearm, Strength)" },
			{ "Serrated Spear", "(lv-16) WEAPON_Serrated Spear (Polearm, Strength)" },
			{ "Sapphite Spear", "(lv-18) WEAPON_Sapphite Spear (Polearm, Strength)" },
			{ "Nulrok Spear", "(lv-20) WEAPON_Nulrok Spear (Polearm, Strength)" },
			{ "Cyrotribe Spear", "(lv-22) WEAPON_Cryotribe Spear (Polearm, Strength)" },
			{ "Flametribe Spear", "(lv-22) WEAPON_Flametribe Spear (Polearm, Strength)" },
			{ "Marrow Bauble", "(lv-2) WEAPON_Marrow Bauble (Scepter, Mind)" },
			{ "Splitbark Scepter", "(lv-2) WEAPON_Splitbark Scepter (Scepter, Mind)" },
			{ "Demicrypt Bauble", "(lv-6) WEAPON_Demicrypt Bauble (Scepter, Mind)" },
			{ "Iron Scepter", "(lv-6) WEAPON_Iron Scepter (Scepter, Mind)" },
			{ "Cryo Cane", "(lv-8) WEAPON_Cryo Cane (Scepter, Mind)" },
			{ "Slime Diva Baton", "(lv-8) WEAPON_Slime Diva Baton (Scepter, Mind)" },
			{ "Pyre Cane", "(lv-12) WEAPON_Pyre Cane (Scepter, Mind)" },
			{ "Wizwand", "(lv-12) WEAPON_Wizwand (Scepter, Mind)" },
			{ "Nethercrypt Bauble", "(lv-14) WEAPON_Nethercrypt Bauble (Scepter, Mind)" },
			{ "Aquapetal Staff", "(lv-16) WEAPON_Aquapetal Staff (Scepter, Mind)" },
			{ "Flamepetal Staff", "(lv-16) WEAPON_Flamepetal Staff (Scepter, Mind)" },
			{ "Mithril Scepter", "(lv-16) WEAPON_Mithril Scepter (Scepter, Mind)" },
			{ "Sapphite Scepter", "(lv-18) WEAPON_Sapphite Scepter (Scepter, Mind)" },
			{ "Voalstark Wand", "(lv-24) WEAPON_Voalstark Wand (Scepter, Mind)" },
			{ "Cryptcall Bell", "(lv-8) WEAPON_Cryptcall Bell (Magic Bell, Mind)" },
			{ "Iron Bell", "(lv-8) WEAPON_Iron Bell (Magic Bell, Mind)" },
			{ "Coldgeist Frostcaller", "(lv-16) WEAPON_Coldgeist Frostcaller (Magic Bell, Mind)" },
			{ "Mithril Bell", "(lv-16) WEAPON_Mithril Bell (Magic Bell, Mind)" },
			{ "Colossus Tone", "(lv-18) WEAPON_Colossus Tone (Magic Bell, Mind)" },
			{ "Sapphite Bell", "(lv-18) WEAPON_Sapphite Bell (Magic Bell, Mind)" },
			{ "Sliemcrust Katars", "(lv-2) WEAPON_Slimecrust Katars (Katars, Dexterity)" },
			{ "Cryptsinge Katars", "(lv-4) WEAPON_Cryptsinge Katars (Katars, Dexterity)" },
			{ "Slimek Shivs", "(lv-4) WEAPON_Slimek Shivs (Katars, Dexterity)" },
			{ "Deathgel Shivs", "(lv-6) WEAPON_Deathgel Shivs (Katars, Dexterity)" },
			{ "Dense Katars", "(lv-6) WEAPON_Dense Katars (Katars, Dexterity)" },
			{ "Iron Katars", "(lv-8) WEAPON_Iron Katars (Katars, Dexterity)" },
			{ "Runic Katars", "(lv-10) WEAPON_Runic Katars (Katars, Dexterity)" },
			{ "Geistlord Claws", "(lv-12) WEAPON_Geistlord Claws (Katars, Dexterity)" },
			{ "Hellsludge Shivs", "(lv-14) WEAPON_Hellsludge Shivs (Katars, Dexterity)" },
			{ "Mithril Katars", "(lv-14) WEAPON_Mithril Katars (Katars, Dexterity)" },
			{ "Frostbite Claws", "(lv-16) WEAPON_Frostbite Claws (Katars, Dexterity)" },
			{ "Serrated Knuckles", "(lv-16) WEAPON_Serrated Knuckles (Katars, Dexterity)" },
			{ "Rummok Bladerings", "(lv-18) WEAPON_Rummok Bladerings (Katars, Dexterity)" },
			{ "Sapphite Katars", "(lv-18) WEAPON_Sapphite Katars (Katars, Dexterity)" },
			{ "Golemfist Katars", "(lv-20) WEAPON_Golemfist Katars (Katars, Dexterity)" },
			{ "Crypt Bow", "(lv-2) WEAPON_Crypt Bow (Bow, Dexterity)" },
			{ "Demicrypt Bow", "(lv-6) WEAPON_Demicrypt Bow (Bow, Dexterity)" },
			{ "Iron Bow", "(lv-6) WEAPON_Iron Bow (Bow, Dexterity)" },
			{ "Mekspike Bow", "(lv-8) WEAPON_Mekspike Bow (Bow, Dexterity)" },
			{ "Menace Bow", "(lv-8) WEAPON_Menace Bow (Bow, Dexterity)" },
			{ "Petrified Bow", "(lv-12) WEAPON_Petrified Bow (Bow, Dexterity)" },
			{ "Mithril Bow", "(lv-14) WEAPON_Mithril Bow (Bow, Dexterity)" },
			{ "Necroroyal Bow", "(lv-14) WEAPON_Necroroyal Bow (Bow, Dexterity)" },
			{ "Colgeist Bow", "(lv-16) WEAPON_Coldgeist Bow (Bow, Dexterity)" },
			{ "Serrated Longbow", "(lv-16) WEAPON_Serrated Longbow (Bow, Dexterity)" },
			{ "Torrentius Longbow", "(lv-24) WEAPON_Torrentius Longbow (Bow, Dexterity)" },
			{ "Amberite Boomstick", "(lv-12) WEAPON_Amberite Boomstick (Shotgun, Dexterity)" },
			{ "Magitek Burstgun", "(lv-20) WEAPON_Magitek Burstgun (Shotgun, Dexterity)" },
			{ "Follycannon", "(lv-26) WEAPON_Follycannon (Shotgun, Dexterity)" },
			{ "Agility Ears", "(lv-1) HELM_Agility Ears" },
			{ "Festive Hat", "(lv-1) HELM_Festive Hat" },
			{ "Fishin Hat", "(lv-1) HELM_Fishin Hat" },
			{ "Leather Cap", "(lv-1) HELM_Leather Cap" },
			{ "Newfold Halo", "(lv-1) HELM_Newfold Halo" },
			{ "Orefinder Hat", "(lv-1) HELM_Orefinder Hat" },
			{ "Spooky Hat", "(lv-1) HELM_Spooky Hat" },
			{ "Top Hat", "(lv-1) HELM_Top Hat" },
			{ "Wizard Hat", "(lv-1) HELM_Wizard Hat" },
			{ "Acolyte Hood", "(lv-4) HELM_Acolyte Hood" },
			{ "Cryptsinge Halo", "(lv-4) HELM_Cryptsinge Halo" },
			{ "Initial Spectacles", "(lv-4) HELM_Initiate Spectacles" },
			{ "Demicrypt Halo", "(lv-6) HELM_Demicrypt Halo" },
			{ "Desne Helm", "(lv-6) HELM_Dense Helm" },
			{ "Diva Crown", "(lv-6) HELM_Diva Crown" },
			{ "Iron Halo", "(lv-6) HELM_Iron Halo" },
			{ "Necromancer Hood", "(lv-8) HELM_Necromancer Hood" },
			{ "Geistlord Crown", "(lv-10) HELM_Geistlord Crown" },
			{ "Journeyman Spectacles", "(lv-10) HELM_Journeyman Spectacles" },
			{ "Amberite Helm", "(lv-12) HELM_Amberite Helm" },
			{ "Focus Circlet", "(lv-12) HELM_Focus Circlet" },
			{ "Magistrate Circlet", "(lv-12) HELM_Magistrate Circlet" },
			{ "Rage Circlet", "(lv-12) HELM_Rage Circlet" },
			{ "Focusi Glasses", "(lv-14) HELM_Focusi Glasses" },
			{ "Nethercrypt Halo", "(lv-14) HELM_Nethercrypt Halo" },
			{ "Carbuncle Hat", "(lv-16) HELM_Carbuncle Hat" },
			{ "Geistlord Eye", "(lv-16) HELM_Geistlord Eye" },
			{ "Glyphgrift Halo", "(lv-16) HELM_Glyphgrift Halo" },
			{ "Jestercast Memory", "(lv-16) HELM_Jestercast Memory" },
			{ "Knightguard Halo", "(lv-16) HELM_Knightguard Halo" },
			{ "Mithril Halo", "(lv-16) HELM_Mithril Halo" },
			{ "Sapphite Mindhat", "(lv-18) HELM_Sapphite Mindhat" },
			{ "Dire Helm", "(lv-22) HELM_Dire Helm" },
			{ "Druidic Halo", "(lv-22) HELM_Druidic Halo" },
			{ "Guardel Helm", "(lv-22) HELM_Guardel Helm" },
			{ "Leathen Cap", "(lv-22) HELM_Leathen Cap" },
			{ "Boarus Helm", "(lv-24) HELM_Boarus Helm" },
			{ "Deathknight Helm", "(lv-24) HELM_Deathknight Helm" },
			{ "Emerock Halo", "(lv-24) HELM_Emerock Halo" },
			{ "Wizlad Hood", "(lv-24) HELM_Wizlad Hood" },
			{ "Boarus Torment", "(lv-26) HELM_Boarus Torment" },
			{ "Initiate Cloak", "(lv-2) CAPE_Initiate Cloak" },
			{ "Slimewoven Cloak", "(lv-4) CAPE_Slimewoven Cloak" },
			{ "Nokket Cloak", "(lv-6) CAPE_Nokket Cloak" },
			{ "Rugged Cloak", "(lv-6) CAPE_Rugged Cloak" },
			{ "Regazuul Cape", "(lv-10) CAPE_Regazuul Cape" },
			{ "Flux Cloak", "(lv-12) CAPE_Flux Cloak" },
			{ "Cozy Cloak", "(lv-14) CAPE_Cozy Cloak" },
			{ "Nethercrypt Cloak", "(lv-14) CAPE_Nethercrypt Cloak" },
			{ "Cobblerage Cloak", "(lv-16) CAPE_Cobblerage Cloak" },
			{ "Deathward Cape", "(lv-16) CAPE_Deathward Cape" },
			{ "Forlorn Cloak", "(lv-16) CAPE_Forlorn Cloak" },
			{ "Meshlink Cape", "(lv-16) CAPE_Meshlink Cape" },
			{ "Sagecaller Cape", "(lv-16) CAPE_Sagecaller Cape" },
			{ "Roudon Cape", "(lv-18) CAPE_Roudon Cape" },
			{ "Blueversa Cape", "(lv-20) CAPE_Blueversa Cape" },
			{ "Greenversa Cape", "(lv-20) CAPE_Greenversa Cape" },
			{ "Nulversa Cape", "(lv-20) CAPE_Nulversa Cape" },
			{ "Redversa Cape", "(lv-20) CAPE_Redversa Cape" },
			{ "Windgolem Cloak", "(lv-22) CAPE_Windgolem Cloak" },
			{ "Mekwar Drape", "(lv-24) CAPE_Mekwar Drape" },
			{ "Aero Top", "(lv-1) CHESTPIECE_Aero Top" },
			{ "Bunhost Garb", "(lv-1) CHESTPIECE_Bunhost Garb" },
			{ "Festive Coat", "(lv-1) CHESTPIECE_Festive Coat" },
			{ "Fisher Overalls", "(lv-1) CHESTPIECE_Fisher Overalls" },
			{ "Leather Top", "(lv-1) CHESTPIECE_Leather Top" },
			{ "Necro Marrow", "(lv-1) CHESTPIECE_Necro Marrow" },
			{ "Noble Shirt", "(lv-1) CHESTPIECE_Noble Shirt" },
			{ "Nutso Top", "(lv-1) CHESTPIECE_Nutso Top" },
			{ "Orefinder Vest", "(lv-1) CHESTPIECE_Orefinder Vest" },
			{ "Ritualist Garb", "(lv-1) CHESTPIECE_Ritualist Garb" },
			{ "Sagecloth Top", "(lv-1) CHESTPIECE_Sagecloth Top" },
			{ "Silken Top", "(lv-1) CHESTPIECE_Silken Top" },
			{ "Spooky Garment", "(lv-1) CHESTPIECE_Spooky Garment" },
			{ "Vampiric Coat", "(lv-1) CHESTPIECE_Vampiric Coat" },
			{ "Ghostly Tabard", "(lv-2) CHESTPIECE_Ghostly Tabard" },
			{ "Poacher Cloth", "(lv-2) CHESTPIECE_Poacher Cloth" },
			{ "Ragged Shirt", "(lv-2) CHESTPIECE_Ragged Shirt" },
			{ "Slimecrust Chest", "(lv-2) CHESTPIECE_Slimecrust Chest" },
			{ "Worn Robe", "(lv-2) CHESTPIECE_Worn Robe" },
			{ "Cryptsinge Chest", "(lv-4) CHESTPIECE_Cryptsinge Chest" },
			{ "Journeyman Vest", "(lv-4) CHESTPIECE_Journeyman Vest" },
			{ "Slimek Chest", "(lv-4) CHESTPIECE_Slimek Chest" },
			{ "Dense Chestpiece", "(lv-6) CHESTPIECE_Dense Chestpiece" },
			{ "Trodd Tunic", "(lv-6) CHESTPIECE_Trodd Tunic" },
			{ "Iron Chestplate", "(lv-7) CHESTPIECE_Iron Chestpiece" },
			{ "Tattered Battlerobe", "(lv-8) CHESTPIECE_Tattered Battlerobe" },
			{ "Apprentice Robe", "(lv-10) CHESTPIECE_Apprentice Robe" },
			{ "Duelist Garb", "(lv-10) CHESTPIECE_Duelist Garb" },
			{ "Skywrill Tabard", "(lv-10) CHESTPIECE_Skywrill Tabard" },
			{ "Sleeper's Robe", "(lv-10) CHESTPIECE_Sleeper's Robe" },
			{ "Warrior Chest", "(lv-10) CHESTPIECE_Warrior Chest" },
			{ "Amberite Breastplate", "(lv-12) CHESTPIECE_Amberite Breastplate" },
			{ "Golem Chestpiece", "(lv-12) CHESTPIECE_Golem Chestpiece" },
			{ "Lord Breastplate", "(lv-12) CHESTPIECE_Lord Breastplate" },
			{ "Nethercrypt Tabard", "(lv-12) CHESTPIECE_Nethercrypt Tabard" },
			{ "Reapsow Garb", "(lv-12) CHESTPIECE_Reapsow Garb" },
			{ "Witchlock Robe", "(lv-12) CHESTPIECE_Witchlock Robe" },
			{ "Chainmail Guard", "(lv-14) CHESTPIECE_Chainmail Guard" },
			{ "Ornamented Battlerobe", "(lv-14) CHESTPIECE_Ornamented Battlerobe" },
			{ "Carbuncle Robe", "(lv-16) CHESTPIECE_Carbuncle Robe" },
			{ "Chainscale Chest", "(lv-16) CHESTPIECE_Chainscale Chest" },
			{ "Gemveil Raiment", "(lv-16) CHESTPIECE_Gemveil Raiment" },
			{ "King Breastplate", "(lv-16) CHESTPIECE_King Breastplate" },
			{ "Mercenary Vestment", "(lv-16) CHESTPIECE_Mercenary Vestment" },
			{ "Mithril Chestpiece", "(lv-16) CHESTPIECE_Mithril Chestpiece" },
			{ "Reaper Gi", "(lv-16) CHESTPIECE_Reaper Gi" },
			{ "Witchwizard Robe", "(lv-16) CHESTPIECE_Witchwizard Robe" },
			{ "Berserker Chestpiece", "(lv-18) CHESTPIECE_Berserker Chestpiece" },
			{ "Fuguefall Duster", "(lv-18) CHESTPIECE_Fuguefall Duster" },
			{ "Magilord Overalls", "(lv-18) CHESTPIECE_Magilord Overalls" },
			{ "Monolith Chestpiece", "(lv-18) CHESTPIECE_Monolith Chestpiece" },
			{ "Sapphite Guard", "(lv-18) CHESTPIECE_Sapphite Guard" },
			{ "Druidic Robe", "(lv-20) CHESTPIECE_Druidic Robe" },
			{ "Emerock Chestpiece", "(lv-20) CHESTPIECE_Emerock Chestpiece" },
			{ "Fortified Chestpiece", "(lv-20) CHESTPIECE_Fortified Vestment" },
			{ "Roudon Chestpiece", "(lv-20) CHESTPIECE_Roudon Chestpiece" },
			{ "Earthbind Tabard", "(lv-22) CHESTPIECE_Earthbind Tabard" },
			{ "Gemveil Breastplate", "(lv-22) CHESTPIECE_Gemveil Breastplate" },
			{ "Roudon Robe", "(lv-22) CHESTPIECE_Roudon Robe" },
			{ "Ruggrok Vest", "(lv-22) CHESTPIECE_Ruggrok Vest" },
			{ "Excecutioner Vestment", "(lv-24) CHESTPIECE_Executioner Vestment" },
			{ "Fender Garb", "(lv-24) CHESTPIECE_Fender Garb" },
			{ "Wizlad Robe", "(lv-24) CHESTPIECE_Wizlad Robe" },
			{ "Aero Pants", "(lv-1) LEGGINGS_Aero Pants" },
			{ "Bunhost Leggings", "(lv-1) LEGGINGS_Bunhost Leggings" },
			{ "Festive Trouser", "(lv-1) LEGGINGS_Festive Trousers" },
			{ "Leather Britches", "(lv-1) LEGGINGS_Leather Britches" },
			{ "Necro Caustics", "(lv-1) LEGGINGS_Necro Caustics" },
			{ "Noble Pants", "(lv-1) LEGGINGS_Noble Pants" },
			{ "Nutso Pants", "(lv-1) LEGGINGS_Nutso Pants" },
			{ "Orefinder", "(lv-1) LEGGINGS_Orefinder Trousers" },
			{ "Ritualist Straps", "(lv-1) LEGGINGS_Ritualist Straps" },
			{ "Sagecloth Shorts", "(lv-1) LEGGINGS_Sagecloth Shorts" },
			{ "Silken Loincloth", "(lv-1) LEGGINGS_Silken Loincloth" },
			{ "Vampiric Leggings", "(lv-1) LEGGINGS_Vampiric Leggings" },
			{ "Ghostly Legwraps", "(lv-2) LEGGINGS_Ghostly Legwraps" },
			{ "Journeyman Shorts", "(lv-2) LEGGINGS_Journeyman Shorts" },
			{ "Slimecrust Leggings", "(lv-2) LEGGINGS_Slimecrust Leggings" },
			{ "Journeyman Leggings", "(lv-4) LEGGINGS_Journeyman Leggings" },
			{ "Slimek Leggings", "(lv-4) LEGGINGS_Slimek Leggings" },
			{ "Dense Leggings", "(lv-6) LEGGINGS_Dense Leggings" },
			{ "Sash Leggings", "(lv-8) LEGGINGS_Sash Leggings" },
			{ "Warrior Leggings", "(lv-10) LEGGINGS_Warrior Leggings" },
			{ "Amberite Leggings", "(lv-12) LEGGINGS_Amberite Leggings" },
			{ "Chainmail Leggings", "(lv-12) LEGGINGS_Chainmail Leggings" },
			{ "Darkcloth Pants", "(lv-12) LEGGINGS_Darkcloth Pants" },
			{ "Lord Greaves", "(lv-12) LEGGINGS_Lord Greaves" },
			{ "Reapsow Pants", "(lv-12) LEGGINGS_Reapsow Pants" },
			{ "Witchlock Loincloth", "(lv-12) LEGGINGS_Witchlock Loincloth" },
			{ "King Greaves", "(lv-16) LEGGINGS_King Greaves" },
			{ "Mercenary Leggings", "(lv-16) LEGGINGS_Mercenary Leggings" },
			{ "Reaper Leggings", "(lv-16) LEGGINGS_Reaper Leggings" },
			{ "Stridebond Pants", "(lv-16) LEGGINGS_Stridebond Pants" },
			{ "Witchwizard Garterbelt", "(lv-16) LEGGINGS_Witchwizard Garterbelt" },
			{ "Berserker Leggings", "(lv-18) LEGGINGS_Berserker Leggings" },
			{ "Fuguefall Pants", "(lv-18) LEGGINGS_Fuguefall Pants" },
			{ "Magilord Boots", "(lv-18) LEGGINGS_Magilord Boots" },
			{ "Sapphite Leggings", "(lv-18) LEGGINGS_Sapphite Leggings" },
			{ "Jadewall Trousers", "(lv-20) LEGGINGS_Jadewail Trousers" },
			{ "Temrak Britches", "(lv-20) LEGGINGS_Temrak Britches" },
			{ "Eschek Greaves", "(lv-22) LEGGINGS_Eschek Greaves" },
			{ "Gemveil Leggings", "(lv-22) LEGGINGS_Gemveil Leggings" },
			{ "Executioner Leggings", "(lv-24) LEGGINGS_Executioner Leggings" },
			{ "Fender Leggings", "(lv-24) LEGGINGS_Fender Leggings" },
			{ "Crypt Buckler", "(lv-4) SHIELD_Crypt Buckler" },
			{ "Slimek Shield", "(lv-4) SHIELD_Slimek Shield" },
			{ "Demicrypt Buckler", "(lv-6) SHIELD_Demicrypt Buckler" },
			{ "Dense Shield", "(lv-6) SHIELD_Dense Shield" },
			{ "Iron Shield", "(lv-6) SHIELD_Iron Shield" },
			{ "Iris Shield", "(lv-8) SHIELD_Iris Shield" },
			{ "Omen Shield", "(lv-8) SHIELD_Omen Shield" },
			{ "Amberite Shield", "(lv-12) SHIELD_Amberite Shield" },
			{ "Slabton Shield", "(lv-12) SHIELD_Slabton Shield" },
			{ "Mithril Shield", "(lv-14) SHIELD_Mithril Shield" },
			{ "Nethercrypt Shield", "(lv-14) SHIELD_Nethercrypt Shield" },
			{ "Rustweary Shield", "(lv-16) SHIELD_Rustweary Shield" },
			{ "Rustwise Shield", "(lv-16) SHIELD_Rustwise Shield" },
			{ "Sapphite Shield", "(lv-18) SHIELD_Sapphite Shield" },
			{ "Rigor Buckler", "(lv-20) SHIELD_Rigor Buckler" },
			{ "Daemon Shield", "(lv-22) SHIELD_Daemon Shield" },
			{ "Irisun Shield", "(lv-22) SHIELD_Irisun Shield" },
			{ "Old Ring", "(lv-1) RING_Old Ring" },
			{ "Ring of Ambition", "(lv-1) RING_Ring Of Ambition" },
			{ "Nograd's Amulet", "(lv-2) RING_Nograd's Amulet" },
			{ "The One Ring", "(lv-2) RING_The One Ring" },
			{ "Ambersquire Ring", "(lv-6) RING_Ambersquire Ring" },
			{ "Emeraldfocus Ring", "(lv-6) RING_Emeraldfocus Ring" },
			{ "Sapphireweave Ring", "(lv-6) RING_Sapphireweave Ring" },
			{ "Edon's Pendant", "(lv-8) RING_Edon's Pendant" },
			{ "Geistlord Ring", "(lv-12) RING_Geistlord Ring" },
			{ "Students Ring", "(lv-12) RING_Students Ring" },
			{ "Pearlpond Ring", "(lv-14) RING_Pearlpond Ring" },
			{ "Slitherwraith Ring", "(lv-14) RING_Slitherwraith Ring" },
			{ "Geistlord Band", "(lv-16) RING_Geistlord Band" },
			{ "Jadetrout Ring", "(lv-16) RING_Jadetrout Ring" },
			{ "Orbos Ring", "(lv-16) RING_Orbos Ring" },
			{ "Valor Ring", "(lv-16) RING_Valor Ring" },
			{ "Earthwoken Ring", "(lv-18) RING_Earthwoken Ring" },
			{ "Noji Talisman", "(lv-20) RING_Noji Talisman" },
			{ "Valdur Effigy", "(lv-24) RING_Valdur Effigy" },
			{ "Glyphik Booklet", "(lv-26) RING_Glyphik Booklet" },
			{ "Tessellated Drive", "(lv-26) RING_Tessellated Drive" },
			{ "Aqua Muchroom Cap", "TRADEITEM_Aqua Muchroom Cap" },
			{ "Barknaught Face", "TRADEITEM_Barknaught Face" },
			{ "Blightwood Log", "TRADEITEM_Blightwood Log" },
			{ "Blightwood Stick", "TRADEITEM_Blightwood Stick" },
			{ "Blue Minchroom Cap", "TRADEITEM_Blue Minchroom Cap" },
			{ "Boomboar Gear", "TRADEITEM_Boomboar Gear" },
			{ "Boomboar Head", "TRADEITEM_Boomboar Head" },
			{ "Boomboar Pouch", "TRADEITEM_Boomboar Pouch" },
			{ "Burnrose", "TRADEITEM_Burnrose" },
			{ "Carbuncle Foot", "TRADEITEM_Carbuncle Foot" },
			{ "Cursed Note", "TRADEITEM_Cursed Note" },
			{ "Deadwood Log", "TRADEITEM_Deadwood Log" },
			{ "Deathgel Core", "TRADEITEM_Deathgel Core" },
			{ "Deathknight Gauntlet", "TRADEITEM_Deathknight Gauntlet" },
			{ "Demigolem Core", "TRADEITEM_Demigolem Core" },
			{ "Demigolem Gem", "TRADEITEM_Demigolem Gem" },
			{ "Diva Necklace", "TRADEITEM_Diva Necklace" },
			{ "Firebreath Gland", "TRADEITEM_Firebreath Gland" },
			{ "Fluxfern", "TRADEITEM_Fluxfern" },
			{ "Gale Muchroom Cap", "TRADEITEM_Gale Muchroom Cap" },
			{ "Geist Collar", "TRADEITEM_Geist Collar" },
			{ "Ghostdust", "TRADEITEM_Ghostdust" },
			{ "Golem Core", "TRADEITEM_Golem Core" },
			{ "Golem Gem", "TRADEITEM_Golem Gem" },
			{ "Green Lipstick", "TRADEITEM_Green Lipstick" },
			{ "Hellsludge Core", "TRADEITEM_Hellsludge Core" },
			{ "Maw Eye", "TRADEITEM_Maw Eye" },
			{ "Mekboar Head", "TRADEITEM_Mekboar Head" },
			{ "Mekboar Spear", "TRADEITEM_Mekboar Spear" },
			{ "Monolith Core", "TRADEITEM_Monolith Core" },
			{ "Monolith Gem", "TRADEITEM_Monolith Gem" },
			{ "Mouth Bittertooth", "TRADEITEM_Mouth Bittertooth" },
			{ "Mouth Eye", "TRADEITEM_Mouth Eye" },
			{ "Rageboar Head", "TRADEITEM_Rageboar Head" },
			{ "Rageboar Spear", "TRADEITEM_Rageboar Spear" },
			{ "Red Minchroom Cap", "TRADEITEM_Red Minchroom Cap" },
			{ "Rock", "TRADEITEM_Rock" },
			{ "Slime Core", "TRADEITEM_Slime Core" },
			{ "Slime Diva Ears", "TRADEITEM_Slime Diva Ears" },
			{ "Slime Ears", "TRADEITEM_Slime Ears" },
			{ "Slimek Core", "TRADEITEM_Slimek Core" },
			{ "Slimek Ears", "TRADEITEM_Slimek Ears" },
			{ "Slimek Eye", "TRADEITEM_Slimek Eye" },
			{ "Vinethorn", "TRADEITEM_Vinethorn" },
			{ "Vout Antennae", "TRADEITEM_Vout Antennae" },
			{ "Vout Wing", "TRADEITEM_Vout Wing" },
			{ "Warboar Axe", "TRADEITEM_Warboar Axe" },
			{ "Warboar Head", "TRADEITEM_Warboar Head" },
			{ "Wizboar Head", "TRADEITEM_Wizboar Head" },
			{ "Wizboar Scepter", "TRADEITEM_Wizboar Scepter" },
			{ "Amberite Ore", "TRADEITEM_Amberite Ore" },
			{ "Dense Ore", "TRADEITEM_Dense Ore" },
			{ "Sapphite Ore", "TRADEITEM_Sapphite Ore" },
			{ "Coal", "TRADEITEM_Coal" },
			{ "Big Wan", "TRADEITEM_Big Wan" },
			{ "Bittering Katfish", "TRADEITEM_Bittering Katfish" },
			{ "Bonefish", "TRADEITEM_Bonefish" },
			{ "Smiling Wrellfish", "TRADEITEM_Smiling Wrellfish" },
			{ "Squangfish", "TRADEITEM_Squangfish" },
			{ "Sugeel", "TRADEITEM_Sugeel" },
			{ "Sugshrimp", "TRADEITEM_Sugshrimp" },
			{ "Windtail Fish", "TRADEITEM_Windtail Fish" },
			{ "Old Boot", "TRADEITEM_Old Boot" },
			{ "Agility Stone", "TRADEITEM_Agility Stone" },
			{ "Angela's Tear", "TRADEITEM_Angela's Tear" },
			{ "Epic Carrot", "TRADEITEM_Epic Carrot" },
			{ "Flux Stone", "TRADEITEM_Flux Stone" },
			{ "Illusion Stone", "TRADEITEM_Illusion Stone" },
			{ "Might Stone", "TRADEITEM_Might Stone" },
			{ "Starlight Gem", "TRADEITEM_Starlight Gem" },
			{ "Black Dye", "TRADEITEM_Black Dye" },
			{ "Blue Dye", "TRADEITEM_Blue Dye" },
			{ "Brown Dye", "TRADEITEM_Brown Dye" },
			{ "Cyan Dye", "TRADEITEM_Cyan Dye" },
			{ "Green Dye", "TRADEITEM_Green Dye" },
			{ "Grey Dye", "TRADEITEM_Grey Dye" },
			{ "Lime Dye", "TRADEITEM_Lime Dye" },
			{ "Orange Dye", "TRADEITEM_Orange Dye" },
			{ "Pink Dye", "TRADEITEM_Pink Dye" },
			{ "Purple Dye", "TRADEITEM_Purple Dye" },
			{ "Red Dye", "TRADEITEM_Red Dye" },
			{ "White Dye", "TRADEITEM_White Dye" },
			{ "Yellow Dye", "TRADEITEM_Yellow Dye" },
			{ "Crowns (Small)", "CURRENCY_250" },
			{ "Crowns (Medium)", "CURRENCY_500" },
			{ "Crowns (Large)", "CURRENCY_1000" },
			{ "Crowns (Huge)", "CURRENCY_2500" },
			{ "Tome of Naivety", "(lv-0) STATUSCONSUMABLE_Tome of Naivety" },
			{ "Tome of Unlearning", "(lv-0) STATUSCONSUMABLE_Tome of Unlearning" },
			{ "Test Chestpiece", "(lv-1) CHESTPIECE_Test Chestpiece" },
			{ "Test Pants", "(lv-1) LEGGINGS_Test Pants" },
			{ "Test Ring", "(lv-1) RING_Test Ring" }
		};

		public static readonly Dictionary<string, List<List<string>>> ProgressiveItemTiers = new Dictionary<string, List<List<string>>>
		{
			{
				"Progressive Any Weapon",
				new List<List<string>>
				{
					new List<string> { "Crypt Buckler", "Slimek Shield" },
					new List<string> { "Demicrypt Buckler", "Dense Shield", "Iron Shield" },
					new List<string> { "Iris Shield", "Omen Shield", "Rustweary Shield", "Rustwise Shield" },
					new List<string> { "Amberite Shield", "Slabton Shield", "Mithril Shield", "Nethercrypt Shield" },
					new List<string> { "Rigor Buckler", "Sapphite Shield", "Daemon Shield", "Irisun Shield" }
				}
			},
			{
				"Progressive Any Helmet",
				new List<List<string>>
				{
					new List<string> { "Agility Ears", "Leather Cap", "Newfold Halo" },
					new List<string> { "Acolyte Hood", "Cryptsinge Halo", "Initial Spectacles", "Demicrypt Halo", "Desne Helm", "Diva Crown" },
					new List<string> { "Iron Halo", "Necromancer Hood", "Journeyman Spectacles" },
					new List<string> { "Geistlord Crown", "Geistlord Eye", "Amberite Helm", "Focus Circlet", "Magistrate Circlet", "Rage Circlet", "Focusi Glasses", "Nethercrypt Halo" },
					new List<string> { "Carbuncle Hat", "Glyphgrift Halo", "Jestercast Memory", "Knightguard Halo", "Mithril Halo", "Wizlad Hood", "Dire Helm", "Druidic Halo", "Guardel Helm", "Leathen Cap" },
					new List<string> { "Sapphite Mindhat", "Boarus Helm", "Deathknight Helm", "Emerock Halo", "Boarus Torment" }
				}
			},
			{
				"Progressive Any Cape",
				new List<List<string>>
				{
					new List<string> { "Initiate Cloak", "Slimewoven Cloak", "Nokket Cloak", "Rugged Cloak" },
					new List<string> { "Cobblerage Cloak", "Forlorn Cloak", "Flux Cloak", "Meshlink Cape", "Cozy Cloak", "Nethercrypt Cloak" },
					new List<string> { "Regazuul Cape", "Deathward Cape", "Sagecaller Cape" },
					new List<string> { "Windgolem Cloak", "Roudon Cape", "Blueversa Cape", "Greenversa Cape", "Nulversa Cape", "Redversa Cape" },
					new List<string> { "Mekwar Drape" }
				}
			},
			{
				"Progressive Any Chest Piece",
				new List<List<string>>
				{
					new List<string> { "Aero Top", "Leather Top", "Necro Marrow", "Nutso Top", "Sagecloth Top", "Ghostly Tabard", "Poacher Cloth", "Ragged Shirt", "Slimecrust Chest", "Worn Robe" },
					new List<string> { "Cryptsinge Chest", "Journeyman Vest", "Slimek Chest", "Apprentice Robe", "Dense Chestpiece", "Trodd Tunic", "Tattered Battlerobe" },
					new List<string> { "Iron Chestplate", "Duelist Garb", "Amberite Breastplate", "Nethercrypt Tabard", "Chainmail Guard", "Skywrill Tabard", "Sleeper's Robe", "Warrior Chest", "Golem Chestpiece", "Carbuncle Robe" },
					new List<string> { "Ornamented Battlerobe", "Chainscale Chest", "Mercenary Vestment", "Mithril Chestpiece", "Druidic Robe" },
					new List<string> { "Gemveil Raiment", "Monolith Chestpiece", "Sapphite Guard", "Fortified Chestpiece", "Roudon Chestpiece", "Roudon Robe", "Earthbind Tabard", "Gemveil Breastplate", "Ruggrok Vest", "Emerock Chestpiece" }
				}
			},
			{
				"Progressive Any Leggings",
				new List<List<string>>
				{
					new List<string> { "Aero Pants", "Leather Britches", "Necro Caustics", "Nutso Pants", "Sagecloth Shorts", "Ghostly Legwraps", "Slimecrust Leggings" },
					new List<string> { "Journeyman Shorts", "Journeyman Leggings", "Slimek Leggings", "Dense Leggings", "Sash Leggings" },
					new List<string> { "Amberite Leggings", "Chainmail Leggings", "Darkcloth Pants", "Warrior Leggings" },
					new List<string> { "Mercenary Leggings", "Stridebond Pants" },
					new List<string> { "Sapphite Leggings", "Jadewall Trousers", "Temrak Britches", "Eschek Greaves", "Gemveil Leggings" }
				}
			},
			{
				"Progressive Any Trinket",
				new List<List<string>>
				{
					new List<string> { "Old Ring", "Ring of Ambition", "Test Ring" },
					new List<string> { "Nograd's Amulet", "Students Ring" },
					new List<string> { "The One Ring", "Geistlord Ring", "Geistlord Band" },
					new List<string> { "Ambersquire Ring", "Emeraldfocus Ring", "Pearlpond Ring", "Slitherwraith Ring", "Jadetrout Ring" },
					new List<string> { "Sapphireweave Ring", "Edon's Pendant", "Orbos Ring", "Valor Ring" },
					new List<string> { "Earthwoken Ring", "Noji Talisman", "Valdur Effigy", "Glyphik Booklet", "Tessellated Drive" }
				}
			},
			{
				"Progressive Fighter Weapon",
				new List<List<string>>
				{
					new List<string> { "Crypt Blade", "Femur Club", "Ironbark Sword", "Slimecrust Blade", "Gilded Sword", "Splitbark Club", "Slimek Axehammer", "Mini Geist Scythe", "Geist Scythe" },
					new List<string>
					{
						"Demicrypt Blade", "Dense Mace", "Iron Sword", "Dense Hammer", "Iron Axehammer", "Crypt Pounder", "Stone Greatblade", "Dense Spear", "Iron Spear", "Cryptsinge Halberd",
						"Dawn Mace", "Rude Blade"
					},
					new List<string> { "Vile Blade", "Poltergeist Scythe", "Mekspear", "Amberite Sword", "Nethercrypt Blade", "Amberite Warstar", "Dolkin's Axe", "Amberite Halberd", "Necroroyal Halberd", "Sinner Bardiche" },
					new List<string> { "Coldgeist Blade", "Mithril Sword", "Serrated Blade", "Mithril Halberd", "Ragespear", "Serrated Spear" },
					new List<string>
					{
						"Nulrok Mace", "Coldgeist Punisher", "Nulrok Spear", "Firebreath Blade", "Quake Pummeler", "Deadwood Axe", "Mithril Greatsword", "Sapphite Spear", "Valdur Blade", "Deathknight Runeblade",
						"Cyrotribe Spear", "Flametribe Spear"
					},
					new List<string> { "Fier Blade", "Ryzer Greataxe" }
				}
			},
			{
				"Progressive Fighter Chest Piece",
				new List<List<string>>
				{
					new List<string> { "Lord Breastplate" },
					new List<string> { "King Breastplate", "Berserker Chestpiece" },
					new List<string> { "Excecutioner Vestment" }
				}
			},
			{
				"Progressive Fighter Leggings",
				new List<List<string>>
				{
					new List<string> { "Lord Greaves" },
					new List<string> { "King Greaves", "Berserker Leggings" },
					new List<string> { "Executioner Leggings" }
				}
			},
			{
				"Progressive Mystic Weapon",
				new List<List<string>>
				{
					new List<string> { "Marrow Bauble", "Splitbark Scepter", "Demicrypt Bauble", "Cryptcall Bell" },
					new List<string> { "Iron Scepter", "Cryo Cane", "Slime Diva Baton", "Iron Bell" },
					new List<string> { "Pyre Cane", "Wizwand", "Nethercrypt Bauble", "Aquapetal Staff", "Flamepetal Staff", "Coldgeist Frostcaller" },
					new List<string> { "Mithril Scepter", "Mithril Bell" },
					new List<string> { "Sapphite Scepter", "Colossus Tone", "Voalstark Wand", "Sapphite Bell" }
				}
			},
			{
				"Progressive Mystic Helmet",
				new List<List<string>>
				{
					new List<string> { "Wizlad Hood" }
				}
			},
			{
				"Progressive Mystic Chest Piece",
				new List<List<string>>
				{
					new List<string> { "Witchlock Robe" },
					new List<string> { "Witchwizard Robe", "Magilord Overalls" },
					new List<string> { "Wizlad Robe" }
				}
			},
			{
				"Progressive Mystic Leggings",
				new List<List<string>>
				{
					new List<string> { "Witchlock Loincloth" },
					new List<string> { "Witchwizard Garterbelt", "Magilord Boots" }
				}
			},
			{
				"Progressive Bandit Weapon",
				new List<List<string>>
				{
					new List<string> { "Sliemcrust Katars", "Cryptsinge Katars", "Slimek Shivs", "Crypt Bow" },
					new List<string> { "Deathgel Shivs", "Dense Katars", "Iron Katars", "Runic Katars", "Demicrypt Bow", "Iron Bow", "Mekspike Bow", "Menace Bow" },
					new List<string> { "Geistlord Claws", "Hellsludge Shivs", "Petrified Bow", "Necroroyal Bow" },
					new List<string> { "Mithril Katars", "Frostbite Claws", "Serrated Knuckles", "Mithril Bow", "Colgeist Bow", "Serrated Longbow", "Amberite Boomstick" },
					new List<string> { "Rummok Bladerings", "Sapphite Katars", "Golemfist Katars", "Torrentius Longbow", "Magitek Burstgun" },
					new List<string> { "Follycannon" }
				}
			},
			{
				"Progressive Bandit Chest Piece",
				new List<List<string>>
				{
					new List<string> { "Reapsow Garb" },
					new List<string> { "Reaper Gi", "Fuguefall Duster" },
					new List<string> { "Fender Garb" }
				}
			},
			{
				"Progressive Bandit Leggings",
				new List<List<string>>
				{
					new List<string> { "Reapsow Pants" },
					new List<string> { "Reaper Leggings", "Fuguefall Pants" },
					new List<string> { "Fender Leggings" }
				}
			}
		};

		private readonly HashSet<string> _completedAchievements = new HashSet<string>();

		private string _lastKnownClass = "";

		private int _lastKnownClassTier = 0;

		private bool _subclassWarningLogged = false;

		private bool _newJourneySent = false;

		private bool _achievementScanDone = false;

		private static readonly Dictionary<string, string[]> BOSS_TO_ACHIEVEMENTS = new Dictionary<string, string[]>
		{
			{
				"Lord Zuulneruda",
				new string[2] { "Clearing Catacombs (1-6)", "Clearing Catacombs (6-12)" }
			},
			{
				"Lord Kaluuz",
				new string[1] { "Clearing Catacombs (12-18)" }
			},
			{
				"Colossus",
				new string[1] { "Clearing Grove (15-20)" }
			},
			{
				"Valdur",
				new string[1] { "Clearing Grove (20-25)" }
			}
		};

		private static readonly Dictionary<string, string[]> BOSS_TO_QUESTS = new Dictionary<string, string[]>
		{
			{
				"Lord Zuulneruda",
				new string[2] { "Communing Catacombs", "The Voice of Zuulneruda" }
			},
			{
				"Lord Kaluuz",
				new string[1] { "Consumed Madness" }
			},
			{
				"Colossus",
				new string[1] { "The Colossus" }
			},
			{
				"Valdur",
				new string[2] { "Hell In The Grove", "Spiraling In The Grove" }
			},
			{
				"Slime Diva",
				new string[1] { "Diva Must Die" }
			}
		};

		private static readonly Dictionary<string, int[]> BOSS_TO_GOALS = new Dictionary<string, int[]>
		{
			{
				"Slime Diva",
				new int[2] { 0, 6 }
			},
			{
				"Lord Zuulneruda",
				new int[2] { 1, 6 }
			},
			{
				"Colossus",
				new int[2] { 2, 6 }
			},
			{
				"Lord Kaluuz",
				new int[2] { 4, 6 }
			},
			{
				"Valdur",
				new int[1] { 5 }
			}
		};

		private readonly HashSet<string> _killedBossNames = new HashSet<string>();

		private MapInstance _lastTrackedMap = null;

		private CreepSpawner _trackedBossSpawner = null;

		private Creep _trackedBoss = null;

		private string _trackedBossName = null;

		private bool _bossDeathFired = false;

		private FileSystemWatcher _profileWatcher = null;

		private bool _pendingAlteredVision = false;

		private DateTime _watcherStartedAt = DateTime.MinValue;

		private string _baselineAppearanceJson = null;

		private string _activeProfilePath = null;

		private static readonly HashSet<string> NoviceSkills = new HashSet<string>
		{
			"Adrenaline", "Alacrity", "Aquos", "Crya", "Curis", "Dexterity Mastery", "Fira", "Focus Shot", "Gust", "Inner Focus",
			"Leg Up", "Life Tap", "Mind Mastery", "Multi Bash", "Recall", "Recovery", "Rock Toss", "Siphon Leech", "Spire", "Spread Shot",
			"Strength Mastery", "Sturdy", "Talus"
		};

		private static Harmony _harmony;

		private static GameObject scriptHolder;

		private static PortalUnlocks portalLocker;

		private static readonly FieldInfo maxOnscreenMessages = AccessTools.Field(typeof(ChatBehaviour), "_maxGameLogicLines");

		public ConfigEntry<string> cfgServer;

		public ConfigEntry<string> cfgSlot;

		public ConfigEntry<string> cfgPassword;

		public ConfigEntry<bool> cfgDeathlink;

		private ConfigEntry<bool> cfgAutoConnect;

		public InputField apServer;

		public InputField apSlot;

		public InputField apPassword;

		public Toggle apDeathlink;

		public ArchipelagoSession _session;

		public bool connected;

		private bool connecting;

		private Dictionary<string, object> slotData = new Dictionary<string, object>();

		public DeathLinkService _dlService;

		public static int reactingToDeathLink;

		private int goalOption = 0;

		public bool randomPortalsEnabled = false;

		public int mainClassOption = 0;

		public int secondaryClassOption = 0;

		private bool shopSanityEnabled = false;

		private int progressivePortalCount = 0;

		private Dictionary<string, int> _progressiveCounts = new Dictionary<string, int>();

		public readonly ConcurrentQueue<Action> _mainThreadQueue = new ConcurrentQueue<Action>();

		private Dictionary<string, bool> _portalItemsReceived = new Dictionary<string, bool>
		{
			{ "Sanctum Portal", false },
			{ "Outer Sanctum Portal", false },
			{ "Arcwood Pass Portal", false },
			{ "Effold Terrace Portal", false },
			{ "Tuul Valley Portal", false },
			{ "Catacombs Portal", false },
			{ "Cresent Road Portal", false },
			{ "Tuul Enclave Portal", false },
			{ "Luvora Garden Portal", false },
			{ "Cresent Keep Portal", false },
			{ "Bularr Fortress Portal", false },
			{ "Cresent Grove lvl 1 Portal", false },
			{ "Cresent Grove lvl 2 Portal", false },
			{ "Gate of the Moon Portal", false },
			{ "Wall of the Stars Portal", false },
			{ "Redwoud Portal", false },
			{ "Trial of the Stars Portal", false }
		};

		private Dictionary<string, string> _portalScenes = new Dictionary<string, string>
		{
			{ "Sanctum Portal", "Assets/Scenes/00_zone_forest/_zone00_sanctum.unity" },
			{ "Outer Sanctum Portal", "Assets/Scenes/00_zone_forest/_zone00_outerSanctum.unity" },
			{ "Arcwood Pass Portal", "Assets/Scenes/00_zone_forest/_zone00_arcwoodPass.unity" },
			{ "Effold Terrace Portal", "Assets/Scenes/00_zone_forest/_zone00_effoldTerrace.unity" },
			{ "Tuul Valley Portal", "Assets/Scenes/00_zone_forest/_zone00_tuulValley.unity" },
			{ "Catacombs Portal", "Assets/Scenes/map_dungeon00_sanctumCatacombs.unity" },
			{ "Cresent Road Portal", "Assets/Scenes/00_zone_forest/_zone00_crescentRoad.unity" },
			{ "Tuul Enclave Portal", "Assets/Scenes/00_zone_forest/_zone00_tuulEnclave.unity" },
			{ "Luvora Garden Portal", "Assets/Scenes/00_zone_forest/_zone00_luvoraGarden.unity" },
			{ "Cresent Keep Portal", "Assets/Scenes/00_zone_forest/_zone00_crescentKeep.unity" },
			{ "Bularr Fortress Portal", "Assets/Scenes/00_zone_forest/_zone00_bularFortress.unity" },
			{ "Cresent Grove lvl 1 Portal", "Assets/Scenes/map_dungeon01_crescentGrove.unity" },
			{ "Cresent Grove lvl 2 Portal", "Assets/Scenes/map_dungeon01_crescentGrove.unity" },
			{ "Gate of the Moon Portal", "Assets/Scenes/00_zone_forest/_zone00_gateOfTheMoon.unity" },
			{ "Wall of the Stars Portal", "Assets/Scenes/00_zone_forest/_zone00_wallOfTheStars.unity" },
			{ "Redwoud Portal", "Assets/Scenes/map_zone00_redwoud.unity" },
			{ "Trial of the Stars Portal", "Assets/Scenes/00_zone_forest/_zone00_trialOfTheStars.unity" }
		};

		private List<string> _progressivePortalOrder = new List<string>
		{
			"Outer Sanctum Portal", "Arcwood Pass Portal", "Catacombs Portal", "Effold Terrace Portal", "Tuul Valley Portal", "Cresent Road Portal", "Luvora Garden Portal", "Cresent Keep Portal", "Tuul Enclave Portal", "Cresent Grove lvl 1 Portal",
			"Bularr Fortress Portal"
		};

		public ArchipelagoShopSanity _shopSanity;

		private readonly HashSet<long> _reportedChecks = new HashSet<long>();

		private int _lastLevel = 0;

		private int _previousFishingLevel = 0;

		private int _previousMiningLevel = 0;

		private HashSet<string> _completedQuests = new HashSet<string>();

		private bool _questDebugLogged = false;

		private string currentSessionId = "";

		private const string SESSION_STATE_FILE = "ap_session_state.dat";

		private int _totalItemsReceived = 0;

		private int _savedItemCount = 0;

		public static AtlyssArchipelagoPlugin Instance { get; private set; }

		public static ManualLogSource StaticLogger { get; private set; }

		public void SendAPChatMessage(string message)
		{
			try
			{
				Player mainPlayer = Player._mainPlayer;
				if (!((Object)(object)mainPlayer == (Object)null))
				{
					ChatBehaviour chatBehaviour = mainPlayer._chatBehaviour;
					if (!((Object)(object)chatBehaviour == (Object)null))
					{
						maxOnscreenMessages.SetValue(chatBehaviour, 50);
						chatBehaviour.Init_GameLogicMessage("<color=#00ff00>[Archipelago]</color> " + message);
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Failed to send chat message: " + ex.Message));
			}
		}

		public void HandleArchipelagoCommand(string message)
		{
			if (!connected || _session == null)
			{
				SendAPChatMessage("<color=#FF4444>Not connected to Archipelago!</color>");
				return;
			}
			string text = message.TrimStart(new char[1] { '/' }).Trim();
			string[] array = text.Split(new char[1] { ' ' }, 2);
			string text2 = array[0].ToLower();
			string text3 = ((array.Length > 1) ? array[1] : "");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[AtlyssAP] Command received: " + text2 + " " + text3));
			switch (text2)
			{
			case "release":
				HandleReleaseCommand();
				return;
			case "collect":
				HandleCollectCommand();
				return;
			case "hint":
				HandleHintCommand(text3);
				return;
			case "help":
				HandleHelpCommand();
				return;
			case "players":
				HandlePlayersCommand();
				return;
			case "status":
				HandleStatusCommand();
				return;
			}
			try
			{
				_session.Socket.SendPacket(new SayPacket
				{
					Text = message
				});
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AtlyssAP] Sent command to server: " + message));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Failed to send command: " + ex.Message));
				SendAPChatMessage("<color=#FF4444>Unknown command: /" + text2 + "</color>");
			}
		}

		private void HandleReleaseCommand()
		{
			try
			{
				_session.Say("!release");
				SendAPChatMessage("<color=#FFFF00>Release requested!</color>");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[AtlyssAP] Release command executed");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Failed to execute release: " + ex.Message));
				SendAPChatMessage("<color=#FF4444>Failed to execute release</color>");
			}
		}

		private void HandleCollectCommand()
		{
			try
			{
				_session.Say("!collect");
				SendAPChatMessage("<color=#FFFF00>Collect requested!</color>");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[AtlyssAP] Collect command executed");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Failed to execute collect: " + ex.Message));
				SendAPChatMessage("<color=#FF4444>Failed to execute collect</color>");
			}
		}

		private void HandleHintCommand(string args)
		{
			try
			{
				if (string.IsNullOrWhiteSpace(args))
				{
					SendAPChatMessage("<color=#FFFF00>Usage: /hint [item name]</color>");
					return;
				}
				SendAPChatMessage("<color=#FFFF00>Requesting hint for: " + args + "</color>");
				_session.Say("!hint " + args);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AtlyssAP] Hint requested for: " + args));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Failed to request hint: " + ex.Message));
			}
		}

		private void HandleHelpCommand()
		{
			SendAPChatMessage("<color=#FFFF00>Archipelago Commands:</color>");
			SendAPChatMessage("/release - Release remaining items");
			SendAPChatMessage("/collect - Collect items from others");
			SendAPChatMessage("/hint [item] - Request hint");
			SendAPChatMessage("/players - List connected players");
			SendAPChatMessage("/status - Show completion status");
			SendAPChatMessage("/help - Show this message");
		}

		private void HandlePlayersCommand()
		{
			try
			{
				IEnumerable<PlayerInfo> allPlayers = _session.Players.AllPlayers;
				int num = 0;
				foreach (PlayerInfo item in allPlayers)
				{
					num++;
				}
				SendAPChatMessage($"<color=#FFFF00>Connected Players ({num}):</color>");
				foreach (PlayerInfo item2 in allPlayers)
				{
					string text = item2.Name ?? $"Player {item2.Slot}";
					string text2 = item2.Game ?? "Unknown";
					SendAPChatMessage("- " + text + " (" + text2 + ")");
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AtlyssAP] Listed {num} players");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Failed to list players: " + ex.Message));
				SendAPChatMessage("<color=#FF4444>Failed to get player list</color>");
			}
		}

		private void HandleStatusCommand()
		{
			try
			{
				int count = _reportedChecks.Count;
				int count2 = AllLocationNameToId.Count;
				int count3 = AllQuestToLocation.Count;
				float num = ((count2 > 0) ? ((float)count / (float)count2 * 100f) : 0f);
				SendAPChatMessage($"<color=#FFFF00>Progress: {count}/{count2} ({num:F1}%)</color>");
				SendAPChatMessage($"Level milestones: {_lastLevel}/32");
				SendAPChatMessage($"Quest completions: {_completedQuests.Count}/{count3}");
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AtlyssAP] Status: {count}/{count2} locations checked");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Failed to show status: " + ex.Message));
			}
		}

		private void OnPacketReceived(ArchipelagoPacketBase packet)
		{
			if (packet is PrintJsonPacket && !(packet is ItemPrintJsonPacket) && !(packet is HintPrintJsonPacket))
			{
				SendAPChatMessage(packet.ToJObject().SelectToken("data[0].text")?.Value<string>() ?? "");
			}
			else if (packet is HintPrintJsonPacket)
			{
				if (packet.ToJObject()["receiving"].ToObject<int>() == _session.Players.ActivePlayer.Slot)
				{
					NetworkItem networkItem = packet.ToJObject()["item"].ToObject<NetworkItem>();
					string alias = _session.Players.GetPlayerInfo(networkItem.Player).Alias;
					string itemName = _session.Items.GetItemName(networkItem.Item);
					string locationNameFromId = _session.Locations.GetLocationNameFromId(networkItem.Location, _session.Players.GetPlayerInfo(networkItem.Player).Game);
					string message = "Your <color=#FFFF00>" + itemName + "</color> is at <color=#FFFF00>" + locationNameFromId + "</color> in <color=#00FFFF>" + alias + "'s</color> world.";
					SendAPChatMessage(message);
				}
				else if (packet.ToJObject()["item"].ToObject<NetworkItem>().Player == _session.Players.ActivePlayer.Slot)
				{
					NetworkItem networkItem2 = packet.ToJObject()["item"].ToObject<NetworkItem>();
					string alias2 = _session.Players.GetPlayerInfo(networkItem2.Player).Alias;
					string itemName2 = _session.Items.GetItemName(networkItem2.Item, _session.Players.GetPlayerInfo(networkItem2.Player).Game);
					string locationNameFromId2 = _session.Locations.GetLocationNameFromId(networkItem2.Location);
					string message = "<color=#00FFFF>" + alias2 + "'s</color> <color=#FFFF00>" + itemName2 + "</color> is at your <color=#FFFF00>" + locationNameFromId2 + "</color>";
					SendAPChatMessage(message);
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"[AtlyssAP] Received a hint for a different player. Ignoring.");
				}
			}
		}

		private void OnDeathLinkReceived(DeathLink dl)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			reactingToDeathLink = 2;
			try
			{
				Player mainPlayer = Player._mainPlayer;
				if ((Object)(object)mainPlayer == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"[AtlyssAP] Player not found for DeathLink! Possibly on Main Menu?");
					reactingToDeathLink = 0;
					return;
				}
				mainPlayer._playerZoneType = (ZoneType)1;
				mainPlayer._statusEntity.Subtract_Health(10000);
				((BaseUnityPlugin)this).Logger.LogMessage((object)"[AtlyssAP] DeathLink Received!");
				string text = ((!string.IsNullOrWhiteSpace(dl.Cause)) ? (dl.Cause + ".") : ("Killed by " + dl.Source + " on Archipelago."));
				try
				{
					GameObject.Find("_GameUI_InGame").GetComponent<ErrorPromptTextManager>().Init_ErrorPrompt(text);
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Failed to display DeathLink message: " + ex.Message));
				}
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Failed to process DeathLink: " + ex2.Message));
				reactingToDeathLink = 0;
			}
		}

		public void ToggleDeathLink(bool enabled)
		{
			if (_session != null && _dlService != null && _session.Socket.Connected)
			{
				if (enabled)
				{
					_dlService.EnableDeathLink();
				}
				else
				{
					_dlService.DisableDeathLink();
				}
			}
		}

		private void PollForLevelChanges()
		{
			try
			{
				Player mainPlayer = Player._mainPlayer;
				if ((Object)(object)mainPlayer == (Object)null)
				{
					return;
				}
				PlayerStats component = ((Component)mainPlayer).GetComponent<PlayerStats>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				int network_currentLevel = component.Network_currentLevel;
				if (network_currentLevel != _lastLevel)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AtlyssAP] Level changed: {_lastLevel} -> {network_currentLevel}");
					if (network_currentLevel >= 2 && network_currentLevel <= 32 && network_currentLevel % 2 == 0)
					{
						string text = $"Reach Level {network_currentLevel}";
						SendCheckByName(text);
						SendAPChatMessage("Found <color=#FFFF00>" + text + "</color>! Sent item to another player!");
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[AtlyssAP] " + text + " milestone!"));
					}
					_lastLevel = network_currentLevel;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Error polling level: " + ex.Message));
			}
		}

		private void PollForSkillLevelChanges()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Player mainPlayer = Player._mainPlayer;
				if ((Object)(object)mainPlayer == (Object)null)
				{
					return;
				}
				PlayerStats pStats = mainPlayer._pStats;
				if ((Object)(object)pStats == (Object)null)
				{
					return;
				}
				for (int i = 0; i < pStats._syncProfessions.Count; i++)
				{
					ProfessionStruct val = pStats._syncProfessions[i];
					ScriptableProfession val2 = null;
					if ((Object)(object)GameManager._current != (Object)null && (Object)(object)GameManager._current._statLogics != (Object)null && i < GameManager._current._statLogics._scriptableProfessions.Length)
					{
						val2 = GameManager._current._statLogics._scriptableProfessions[i];
					}
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					if (val2._professionName == "Fishing")
					{
						int professionLvl = val._professionLvl;
						if (professionLvl > _previousFishingLevel)
						{
							for (int j = _previousFishingLevel + 1; j <= professionLvl; j++)
							{
								string text = $"Fishing Lv. {j}";
								SendCheckByName(text);
								SendAPChatMessage("Found <color=#FFFF00>" + text + "</color>! Sent item to another player!");
								((BaseUnityPlugin)this).Logger.LogInfo((object)("[AtlyssAP] " + text + " reached!"));
							}
							_previousFishingLevel = professionLvl;
						}
					}
					if (!(val2._professionName == "Mining"))
					{
						continue;
					}
					int professionLvl2 = val._professionLvl;
					if (professionLvl2 > _previousMiningLevel)
					{
						for (int k = _previousMiningLevel + 1; k <= professionLvl2; k++)
						{
							string text2 = $"Mining Lv. {k}";
							SendCheckByName(text2);
							SendAPChatMessage("Found <color=#FFFF00>" + text2 + "</color>! Sent item to another player!");
							((BaseUnityPlugin)this).Logger.LogInfo((object)("[AtlyssAP] " + text2 + " reached!"));
						}
						_previousMiningLevel = professionLvl2;
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Error checking skill levels: " + ex.Message));
			}
		}

		private void PollForQuestCompletions()
		{
			try
			{
				Player mainPlayer = Player._mainPlayer;
				if ((Object)(object)mainPlayer == (Object)null)
				{
					return;
				}
				PlayerQuesting component = ((Component)mainPlayer).GetComponent<PlayerQuesting>();
				if ((Object)(object)component == (Object)null || component._finishedQuests == null)
				{
					return;
				}
				if (!_questDebugLogged && component._finishedQuests.Count > 0)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AtlyssAP] DEBUG: Found {component._finishedQuests.Count} completed quests");
					foreach (string key2 in component._finishedQuests.Keys)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[AtlyssAP] DEBUG: Completed quest: '" + key2 + "'"));
					}
					_questDebugLogged = true;
				}
				foreach (KeyValuePair<string, long> item in AllQuestToLocation)
				{
					string key = item.Key;
					long value = item.Value;
					if (component._finishedQuests.ContainsKey(key) && !_completedQuests.Contains(key))
					{
						SendCheckById(value);
						_completedQuests.Add(key);
						SendAPChatMessage("Found <color=#FFFF00>" + key + "</color>! Sent item to another player!");
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[AtlyssAP] Quest completed: " + key));
					}
				}
				CheckGoalCompletion(mainPlayer, component);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Error polling quests: " + ex.Message));
			}
		}

		public void SendCheckById(long locationId)
		{
			if (!connected || _session == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[AtlyssAP] Not connected; cannot send check.");
			}
			else
			{
				if (_reportedChecks.Contains(locationId))
				{
					return;
				}
				try
				{
					if (_session != null && _session.Socket != null && _session.Socket.Connected)
					{
						_session.Locations.CompleteLocationChecks(locationId);
						_reportedChecks.Add(locationId);
						((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AtlyssAP] Sent check ID: {locationId}");
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Failed to send check: " + ex.Message));
				}
			}
		}

		public void SendCheckByName(string locationName)
		{
			if (AllLocationNameToId.TryGetValue(locationName, out var value))
			{
				SendCheckById(value);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[AtlyssAP] Location not found in DataTables: '" + locationName + "'"));
			}
		}

		public void SendGoalComplete()
		{
			if (_goalSent || _session == null)
			{
				return;
			}
			try
			{
				_session.Socket.SendPacket(new StatusUpdatePacket
				{
					Status = ArchipelagoClientState.ClientGoal
				});
				_goalSent = true;
				SendAPChatMessage("<color=#FFD700>GOAL COMPLETE!</color> <color=#FFFF00>You have achieved your objective!</color>");
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AtlyssAP] Goal met (option {goalOption}) — sent ClientGoal to server.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[AtlyssAP] Failed to send goal completion: " + ex.Message));
			}
		}

		private bool CheckAllQuestsFromProfile()
		{
			try
			{
				float unscaledTime = Time.unscaledTime;
				if (unscaledTime - _lastAllQuestsCheck < 5f)
				{
					return false;
				}
				_lastAllQuestsCheck = unscaledTime;
				string activeProfilePath = _activeProfilePath;
				if (string.IsNul