Decompiled source of POE Crafting v0.1.8

plugins/POECrafting/POECrafting.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using POECrafting.Core;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("POECrafting")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.8.0")]
[assembly: AssemblyInformationalVersion("0.1.8")]
[assembly: AssemblyProduct("POECrafting")]
[assembly: AssemblyTitle("POECrafting")]
[assembly: AssemblyVersion("0.1.8.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace POECrafting
{
	internal sealed class CorruptionGuard
	{
		internal const string Key = "local.valheim.poecrafting.corrupted.v1";

		private static Type tableUi;

		private static Type element;

		private static FieldInfo consumed;

		private static FieldInfo crafted;

		private static MethodInfo selected;

		private static FieldInfo availableItems;

		private static FieldInfo temperSelected;

		private static FieldInfo temperItem;

		internal bool Ready { get; }

		internal static bool IsCorrupted(ItemData? item)
		{
			return item?.m_customData.ContainsKey("local.valheim.poecrafting.corrupted.v1") ?? false;
		}

		internal static void Mark(ItemData item)
		{
			item.m_customData["local.valheim.poecrafting.corrupted.v1"] = "1";
		}

		internal CorruptionGuard(Harmony harmony, EpicLootBridge bridge)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Expected O, but got Unknown
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Expected O, but got Unknown
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Expected O, but got Unknown
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Expected O, but got Unknown
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_0392: Expected O, but got Unknown
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Expected O, but got Unknown
			//IL_03c8: Expected O, but got Unknown
			foreach (MethodInfo item in from m in AccessTools.GetDeclaredMethods(typeof(ItemData))
				where m.Name == "GetTooltip" && !m.IsStatic && m.ReturnType == typeof(string)
				select m)
			{
				harmony.Patch((MethodBase)item, (HarmonyMethod)null, new HarmonyMethod(typeof(CorruptionGuard), "TooltipPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			Assembly assembly = bridge.ApiType.Assembly;
			tableUi = assembly.GetType("EpicLoot_UnityLib.EnchantingTableUI", throwOnError: true);
			element = assembly.GetType("EpicLoot_UnityLib.InventoryItemListElement", throwOnError: true);
			availableItems = RequiredField(assembly.GetType("EpicLoot_UnityLib.EnchantingTableUIPanelBase", throwOnError: true), "AvailableItems");
			selected = availableItems.FieldType.GetMethods().Single((MethodInfo m) => m.Name == "GetSelectedItems" && m.IsGenericMethodDefinition).MakeGenericMethod(element);
			Type temperType = assembly.GetType("EpicLoot.TemperPanel", throwOnError: true);
			temperSelected = RequiredField(temperType, "selectedItemElement");
			temperItem = RequiredField(temperSelected.FieldType, "_item");
			Type type = assembly.GetType("EpicLoot.Crafting.TransferMagicalEffects", throwOnError: true);
			consumed = RequiredField(type, "ConsumedMagicItems");
			crafted = RequiredField(type, "CraftedItem");
			Type uiType = assembly.GetType("EpicLoot.CraftingV2.EnchantingUIController", throwOnError: true);
			MethodInfo[] array = new string[4] { "EnchantUI", "AugmentUI", "RuneUI", "DisenchantUI" }.Select((string n) => RequiredMethod(assembly.GetType("EpicLoot_UnityLib." + n, throwOnError: true), "DoMainAction")).ToArray();
			MethodInfo[] array2 = new string[4] { "GetEnchantableItems", "GetAugmentableItems", "GetRuneModifyableItems", "GetDisenchantItems" }.Select((string n) => RequiredMethod(uiType, n)).ToArray();
			MethodInfo[] array3 = new string[2] { "OnStartTemper", "OnTemper" }.Select((string n) => RequiredMethod(temperType, n)).ToArray();
			MethodInfo methodInfo = RequiredMethod(type, "TransferMagicToCraftedItem");
			MethodInfo[] array4 = array;
			foreach (MethodInfo methodInfo2 in array4)
			{
				harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(CorruptionGuard), "PanelPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			array4 = array2;
			foreach (MethodInfo methodInfo3 in array4)
			{
				harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(CorruptionGuard), "FilterPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			array4 = array3;
			foreach (MethodInfo methodInfo4 in array4)
			{
				harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeof(CorruptionGuard), "TemperPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			harmony.Patch((MethodBase)RequiredMethod(temperType, "CanTemper"), (HarmonyMethod)null, new HarmonyMethod(typeof(CorruptionGuard), "CanTemperPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)RequiredMethod(bridge.ApiType, "ApplyMagicItemJson"), new HarmonyMethod(typeof(CorruptionGuard), "ApplyPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(CorruptionGuard), "TransferPrefix", (Type[])null), new HarmonyMethod(typeof(CorruptionGuard), "TransferPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Ready = bridge.Version == "0.14.13";
		}

		private static MethodInfo RequiredMethod(Type type, string name)
		{
			return AccessTools.Method(type, name, (Type[])null, (Type[])null) ?? throw new MissingMethodException(type.FullName, name);
		}

		private static FieldInfo RequiredField(Type type, string name)
		{
			return AccessTools.Field(type, name) ?? throw new MissingFieldException(type.FullName, name);
		}

		internal static bool NativeUiVisible()
		{
			if (tableUi != null)
			{
				return (bool)RequiredMethod(tableUi, "IsVisible").Invoke(null, null);
			}
			return false;
		}

		private static void TooltipPostfix(ItemData __instance, ref string __result)
		{
			if (IsCorrupted(__instance))
			{
				__result += "\n<color=#d45454>Corrupted — enchantments are locked</color>";
			}
		}

		private static bool PanelPrefix(object __instance)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			try
			{
				foreach (object item in (IEnumerable)selected.Invoke(availableItems.GetValue(__instance), null))
				{
					object value = item.GetType().GetProperty("Item1").GetValue(item, null);
					if (IsCorrupted((ItemData)element.GetField("Item").GetValue(value)))
					{
						Notify();
						return false;
					}
				}
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Instance.LogError("Corruption selection check failed: " + ex);
				return false;
			}
		}

		private static void FilterPostfix(object __result)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			if (!(__result is IList list))
			{
				return;
			}
			for (int num = list.Count - 1; num >= 0; num--)
			{
				if (IsCorrupted((ItemData)element.GetField("Item").GetValue(list[num])))
				{
					list.RemoveAt(num);
				}
			}
		}

		private static ItemData? TemperTarget(object panel)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			object value = temperSelected.GetValue(panel);
			if (value != null)
			{
				return (ItemData)temperItem.GetValue(value);
			}
			return null;
		}

		private static bool TemperPrefix(object __instance)
		{
			if (!IsCorrupted(TemperTarget(__instance)))
			{
				return true;
			}
			Notify();
			return false;
		}

		private static void CanTemperPostfix(object __instance, ref bool __result)
		{
			if (IsCorrupted(TemperTarget(__instance)))
			{
				__result = false;
			}
		}

		private static bool ApplyPrefix(ItemData __0, ref bool __result)
		{
			if (!IsCorrupted(__0))
			{
				return true;
			}
			__result = false;
			return false;
		}

		private static void TransferPrefix(out bool __state)
		{
			__state = ((IEnumerable)consumed.GetValue(null)).Cast<ItemData>().Any(IsCorrupted);
		}

		private static void TransferPostfix(bool __state)
		{
			if (__state)
			{
				object? value = crafted.GetValue(null);
				ItemData val = (ItemData)((value is ItemData) ? value : null);
				if (val != null)
				{
					Mark(val);
				}
			}
		}

		private static void Notify()
		{
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Corrupted equipment cannot be enchanted again.", 0, (Sprite)null, false);
			}
		}
	}
	internal sealed class CraftingPanel
	{
		private readonly Plugin plugin;

		private readonly Random random = new Random();

		private ItemData? target;

		private Currency currency;

		private Vector2 itemScroll;

		private Vector2 currencyScroll;

		private Vector2 detailScroll;

		private Vector2 resultScroll;

		private bool currencySelected;

		private bool pendingTableOpen;

		private string confirmationJson = "";

		private string message = "";

		private Rect window;

		private GUISkin? skin;

		private Texture2D? panelBackground;

		private Texture2D? buttonBackground;

		private Texture2D? hoverBackground;

		private Texture2D? selectionBackground;

		private GUIStyle? selectedButton;

		private GUIStyle? tooltipStyle;

		private GUIStyle? rowStyle;

		private GUIStyle? rightLabel;

		private GUIStyle? smallLabel;

		private GUIStyle? cardStyle;

		private ItemData[] equipment = Array.Empty<ItemData>();

		private readonly Dictionary<Currency, int> counts = new Dictionary<Currency, int>();

		private readonly Dictionary<Currency, string?> availability = new Dictionary<Currency, string>();

		private readonly Dictionary<ItemData, string> itemTooltips = new Dictionary<ItemData, string>();

		private JObject? selectedMagic;

		private string selectedDetails = "";

		private string selectedSummary = "";

		private string uiError = "";

		private float refreshAt;

		private string hoveredTooltip = "";

		private Vector2 tooltipMouse;

		private Rect hoverViewport;

		private static readonly Currency[] MenuOrder;

		internal bool IsOpen { get; private set; }

		internal CraftingPanel(Plugin plugin)
		{
			this.plugin = plugin;
		}

		internal void Update()
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (pendingTableOpen && !CorruptionGuard.NativeUiVisible())
			{
				pendingTableOpen = false;
				if (Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead() && !((Character)localPlayer).InCutscene() && NearTable(localPlayer) && !InventoryGui.IsVisible())
				{
					Chat instance = Chat.instance;
					if ((instance == null || !instance.HasFocus()) && !Menu.IsVisible() && !Console.IsVisible())
					{
						Open();
					}
				}
			}
			if (IsOpen && (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).InCutscene() || !NearTable(localPlayer)))
			{
				Close();
				return;
			}
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).InCutscene())
			{
				return;
			}
			if (IsOpen)
			{
				RefreshUi(localPlayer);
			}
			if (Input.GetKeyDown(plugin.OpenKey.Value))
			{
				if (IsOpen)
				{
					Close();
					return;
				}
				if (!NearTable(localPlayer))
				{
					((Character)localPlayer).Message((MessageType)2, "Stand within four metres of an Epic Loot enchanting table.", 0, (Sprite)null, false);
					return;
				}
				if (!CorruptionGuard.NativeUiVisible() && !InventoryGui.IsVisible())
				{
					Chat instance2 = Chat.instance;
					if ((instance2 == null || !instance2.HasFocus()) && !Menu.IsVisible() && !Console.IsVisible())
					{
						Open();
						goto IL_0148;
					}
				}
				((Character)localPlayer).Message((MessageType)2, "Close other windows before opening currency crafting.", 0, (Sprite)null, false);
				return;
			}
			goto IL_0148;
			IL_0148:
			if (IsOpen && Input.GetKeyDown((KeyCode)27))
			{
				Close();
			}
		}

		internal void OpenFromTable()
		{
			pendingTableOpen = true;
		}

		private void Open()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			if (!IsOpen)
			{
				target = null;
				currencySelected = false;
				message = "";
				itemTooltips.Clear();
				refreshAt = 0f;
				detailScroll = (resultScroll = Vector2.zero);
				float num = Math.Min(900, Screen.width - 24);
				float num2 = Math.Min(660, Screen.height - 24);
				window = new Rect(Math.Max(0f, ((float)Screen.width - num) / 2f), Math.Max(0f, ((float)Screen.height - num2) / 2f), num, num2);
				IsOpen = true;
				GUIManager.BlockInput(true);
			}
		}

		internal void Close()
		{
			pendingTableOpen = false;
			if (IsOpen)
			{
				IsOpen = false;
				hoveredTooltip = "";
				GUIManager.BlockInput(false);
			}
		}

		internal void Dispose()
		{
			Close();
			if (Object.op_Implicit((Object)(object)skin))
			{
				Object.Destroy((Object)(object)skin);
			}
			if (Object.op_Implicit((Object)(object)panelBackground))
			{
				Object.Destroy((Object)(object)panelBackground);
			}
			if (Object.op_Implicit((Object)(object)buttonBackground))
			{
				Object.Destroy((Object)(object)buttonBackground);
			}
			if (Object.op_Implicit((Object)(object)hoverBackground))
			{
				Object.Destroy((Object)(object)hoverBackground);
			}
			if (Object.op_Implicit((Object)(object)selectionBackground))
			{
				Object.Destroy((Object)(object)selectionBackground);
			}
		}

		private static bool NearTable(Player player)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Collider[] array = Physics.OverlapSphere(((Component)player).transform.position, 4f);
			for (int i = 0; i < array.Length; i++)
			{
				Transform val = ((Component)array[i]).transform;
				while ((Object)(object)val != (Object)null)
				{
					if (((Object)val).name.StartsWith("piece_enchantingtable", StringComparison.Ordinal))
					{
						return true;
					}
					val = val.parent;
				}
			}
			return false;
		}

		private static bool Equipment(ItemData item)
		{
			if (item.m_equipped || item.m_stack != 1)
			{
				return false;
			}
			string value = ((object)Unsafe.As<ItemType, ItemType>(ref item.m_shared.m_itemType)/*cast due to .constrained prefix*/).ToString();
			return new string[12]
			{
				"OneHandedWeapon", "TwoHandedWeapon", "TwoHandedWeaponLeft", "Bow", "Bows", "Crossbow", "Crossbows", "Shield", "Helmet", "Chest",
				"Legs", "Shoulder"
			}.Contains(value);
		}

		private static string GuardEffect(ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			if ((int)item.m_shared.m_itemType != 5)
			{
				return "ModifyArmor";
			}
			return "ModifyBlockPower";
		}

		private static bool IsWeapon(ItemData item)
		{
			if (!((object)Unsafe.As<ItemType, ItemType>(ref item.m_shared.m_itemType)/*cast due to .constrained prefix*/).ToString().Contains("Weapon") && !((object)Unsafe.As<ItemType, ItemType>(ref item.m_shared.m_itemType)/*cast due to .constrained prefix*/).ToString().Contains("Bow"))
			{
				return ((object)Unsafe.As<ItemType, ItemType>(ref item.m_shared.m_itemType)/*cast due to .constrained prefix*/).ToString().Contains("bow");
			}
			return true;
		}

		internal void Draw()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (!IsOpen)
			{
				return;
			}
			GUISkin val = GUI.skin;
			Color color = GUI.color;
			Color contentColor = GUI.contentColor;
			Color backgroundColor = GUI.backgroundColor;
			bool enabled = GUI.enabled;
			try
			{
				EnsureSkin();
				GUI.skin = skin;
				GUI.color = (GUI.contentColor = (GUI.backgroundColor = Color.white));
				GUI.enabled = true;
				window = GUI.Window(738251, window, new WindowFunction(DrawWindow), "POE Currency Crafting");
			}
			finally
			{
				GUI.skin = val;
				GUI.color = color;
				GUI.contentColor = contentColor;
				GUI.backgroundColor = backgroundColor;
				GUI.enabled = enabled;
			}
		}

		private void EnsureSkin()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Expected O, but got Unknown
			//IL_02c1: Expected O, but got Unknown
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Expected O, but got Unknown
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Expected O, but got Unknown
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Expected O, but got Unknown
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Expected O, but got Unknown
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_041c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Expected O, but got Unknown
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_043b: Expected O, but got Unknown
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Expected O, but got Unknown
			//IL_0483: Unknown result type (might be due to invalid IL or missing references)
			//IL_0488: Unknown result type (might be due to invalid IL or missing references)
			//IL_0494: Expected O, but got Unknown
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c0: Expected O, but got Unknown
			//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e2: Expected O, but got Unknown
			//IL_04e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ed: Expected O, but got Unknown
			//IL_04f2: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)skin))
			{
				return;
			}
			skin = Object.Instantiate<GUISkin>(GUI.skin);
			panelBackground = SolidTexture(new Color(0.1f, 0.085f, 0.065f, 1f));
			buttonBackground = SolidTexture(new Color(0.22f, 0.19f, 0.14f, 1f));
			hoverBackground = SolidTexture(new Color(0.36f, 0.3f, 0.19f, 1f));
			selectionBackground = new Texture2D(3, 3);
			for (int i = 0; i < 3; i++)
			{
				for (int j = 0; j < 3; j++)
				{
					selectionBackground.SetPixel(i, j, (i == 1 && j == 1) ? new Color(0.18f, 0.15f, 0.1f) : new Color(0.85f, 0.65f, 0.28f));
				}
			}
			((Texture)selectionBackground).filterMode = (FilterMode)0;
			selectionBackground.Apply();
			GUIStyleState[] array = (GUIStyleState[])(object)new GUIStyleState[8]
			{
				skin.window.normal,
				skin.window.hover,
				skin.window.active,
				skin.window.focused,
				skin.window.onNormal,
				skin.window.onHover,
				skin.window.onActive,
				skin.window.onFocused
			};
			int k;
			for (k = 0; k < array.Length; k++)
			{
				SetStyleState(array[k], panelBackground);
			}
			array = (GUIStyleState[])(object)new GUIStyleState[2]
			{
				skin.button.normal,
				skin.button.onNormal
			};
			for (k = 0; k < array.Length; k++)
			{
				SetStyleState(array[k], buttonBackground);
			}
			array = (GUIStyleState[])(object)new GUIStyleState[6]
			{
				skin.button.hover,
				skin.button.active,
				skin.button.focused,
				skin.button.onHover,
				skin.button.onActive,
				skin.button.onFocused
			};
			for (k = 0; k < array.Length; k++)
			{
				SetStyleState(array[k], hoverBackground);
			}
			GUIStyle obj = skin.window;
			GUIStyle button = skin.button;
			RectOffset val = new RectOffset();
			RectOffset border = val;
			button.border = val;
			obj.border = border;
			skin.window.padding = new RectOffset(14, 14, 32, 14);
			skin.window.fontSize = 16;
			skin.label.normal.textColor = Color.white;
			GUIStyle label = skin.label;
			k = (skin.button.fontSize = 14);
			label.fontSize = k;
			GUIStyle label2 = skin.label;
			bool wordWrap = (skin.button.wordWrap = true);
			label2.wordWrap = wordWrap;
			skin.label.richText = true;
			skin.button.padding = new RectOffset(8, 8, 6, 6);
			selectedButton = new GUIStyle(skin.button);
			selectedButton.border = new RectOffset(1, 1, 1, 1);
			array = (GUIStyleState[])(object)new GUIStyleState[4] { selectedButton.normal, selectedButton.hover, selectedButton.active, selectedButton.focused };
			for (k = 0; k < array.Length; k++)
			{
				SetStyleState(array[k], selectionBackground);
			}
			tooltipStyle = new GUIStyle(skin.label)
			{
				padding = new RectOffset(12, 12, 10, 10),
				wordWrap = true
			};
			SetStyleState(tooltipStyle.normal, panelBackground);
			rowStyle = new GUIStyle(skin.label)
			{
				alignment = (TextAnchor)3,
				wordWrap = false,
				clipping = (TextClipping)1
			};
			rightLabel = new GUIStyle(rowStyle)
			{
				alignment = (TextAnchor)5
			};
			smallLabel = new GUIStyle(skin.label)
			{
				fontSize = 12,
				wordWrap = false,
				clipping = (TextClipping)1
			};
			cardStyle = new GUIStyle(skin.box)
			{
				padding = new RectOffset(10, 10, 8, 8),
				border = new RectOffset()
			};
			SetStyleState(cardStyle.normal, buttonBackground);
		}

		private static Texture2D SolidTexture(Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, color);
			val.Apply();
			return val;
		}

		private static void SetStyleState(GUIStyleState state, Texture2D background)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			state.background = background;
			state.textColor = Color.white;
		}

		private void DrawWindow(int id)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Invalid comparison between Unknown and I4
			//IL_050b: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Invalid comparison between Unknown and I4
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Invalid comparison between Unknown and I4
			//IL_054d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0604: Unknown result type (might be due to invalid IL or missing references)
			//IL_0625: Unknown result type (might be due to invalid IL or missing references)
			//IL_062f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0634: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Invalid comparison between Unknown and I4
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Invalid comparison between Unknown and I4
			//IL_06d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_068b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0723: Unknown result type (might be due to invalid IL or missing references)
			//IL_0729: Invalid comparison between Unknown and I4
			//IL_06fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_0488: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
			tooltipMouse = Event.current.mousePosition;
			if ((int)Event.current.type == 7)
			{
				hoveredTooltip = "";
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				Close();
				return;
			}
			RefreshUi(localPlayer);
			if (GUI.Button(new Rect(((Rect)(ref window)).width - 80f, 27f, 66f, 24f), "Close"))
			{
				Close();
			}
			float num = Math.Min(154f, ((Rect)(ref window)).height * 0.24f);
			float num2 = Math.Min(88f, ((Rect)(ref window)).height * 0.25f);
			float num3 = Math.Max(40f, ((Rect)(ref window)).height - 54f - num - num2 - 30f);
			float num4 = (((Rect)(ref window)).width - 40f) / 2f;
			GUILayout.BeginArea(new Rect(14f, 54f, num4, num3));
			GUILayout.Label("Select an item · unequipped equipment", Array.Empty<GUILayoutOption>());
			SetHoverViewport(num4, num3);
			itemScroll = GUILayout.BeginScrollView(itemScroll, Array.Empty<GUILayoutOption>());
			bool flag = false;
			ItemData[] array = equipment;
			foreach (ItemData val in array)
			{
				string text = Localization.instance.Localize(val.m_shared.m_name);
				bool selected = target == val;
				int num5 = plugin.Bridge.Rarity(val);
				string text2 = ((num5 >= 0 && num5 <= 5) ? CurrencyDropRules.QualityName(num5) : "Ordinary");
				if (CorruptionGuard.IsCorrupted(val))
				{
					text2 += " · Corrupted";
				}
				Rect rect = GUILayoutUtility.GetRect(0f, 44f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				string value = "";
				if (IsHovered(rect) && !itemTooltips.TryGetValue(val, out value))
				{
					value = (itemTooltips[val] = text + "\n" + Localization.instance.Localize(val.GetTooltip(-1)));
				}
				if (DrawRow(rect, val.GetIcon(), text, text2, "", value, RarityColor(num5), selected, dim: false))
				{
					target = val;
					detailScroll = Vector2.zero;
					flag = true;
				}
			}
			GUILayout.EndScrollView();
			GUILayout.EndArea();
			GUILayout.BeginArea(new Rect(26f + num4, 54f, num4, num3));
			GUILayout.Label("Select a currency · hover for its effect", Array.Empty<GUILayoutOption>());
			SetHoverViewport(num4, num3);
			currencyScroll = GUILayout.BeginScrollView(currencyScroll, Array.Empty<GUILayoutOption>());
			Currency[] menuOrder = MenuOrder;
			foreach (Currency val2 in menuOrder)
			{
				if ((int)val2 == 0 || (int)val2 == 14 || (int)val2 == 9)
				{
					GUILayout.Label(((int)val2 == 0) ? "Orbs" : (((int)val2 == 14) ? "Shard crafting" : "Essences"), smallLabel, Array.Empty<GUILayoutOption>());
				}
				counts.TryGetValue(val2, out var value2);
				availability.TryGetValue(val2, out string value3);
				bool selected2 = currencySelected && currency == val2;
				string text4 = CurrencyItems.Description(val2);
				text4 = text4 + "\nMinimum drop tier: " + CurrencyDropRules.MinimumQualityName(val2) + ".";
				if (((int)val2 == 3 || (int)val2 == 15) && selectedMagic != null)
				{
					text4 = text4 + "\nSelected item limit: " + plugin.Bridge.MaximumEffects((int)selectedMagic["Rarity"]) + " effects.";
				}
				if (value3 != null)
				{
					text4 = text4 + "\n\n" + value3;
				}
				GameObject val3 = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(CurrencyItems.Prefab(val2)) : null);
				object obj;
				if (!Object.op_Implicit((Object)(object)val3))
				{
					obj = null;
				}
				else
				{
					ItemDrop component = val3.GetComponent<ItemDrop>();
					obj = ((component != null) ? component.m_itemData.GetIcon() : null);
				}
				Sprite icon = (Sprite)obj;
				Rect rect2 = GUILayoutUtility.GetRect(0f, 44f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				string subtitle = ((value3 == null) ? "" : ((value2 == 0) ? "None owned" : ((value3.Length > 48) ? (value3.Substring(0, 45) + "…") : value3)));
				if (DrawRow(rect2, icon, CurrencyItems.Name(val2), subtitle, "×" + value2, text4, RarityColor(CurrencyDropRules.MinimumQuality(val2)), selected2, value3 != null))
				{
					currency = val2;
					currencySelected = true;
					flag = true;
				}
			}
			GUILayout.EndScrollView();
			GUILayout.EndArea();
			if (flag)
			{
				RefreshUi(localPlayer, force: true);
			}
			float num6 = 64f + num3;
			GUILayout.BeginArea(new Rect(14f, num6, num4, num), cardStyle);
			if (target != null)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				DrawIcon(GUILayoutUtility.GetRect(38f, 38f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(38f) }), target.GetIcon());
				GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
				GUILayout.Label(Localization.instance.Localize(target.m_shared.m_name), rowStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label(selectedSummary, smallLabel, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				GUILayout.EndHorizontal();
				detailScroll = GUILayout.BeginScrollView(detailScroll, Array.Empty<GUILayoutOption>());
				GUILayout.Label(selectedDetails, Array.Empty<GUILayoutOption>());
				GUILayout.EndScrollView();
			}
			else
			{
				GUILayout.Label("Select equipment above to inspect its effects and shard slots.", Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndArea();
			GUILayout.BeginArea(new Rect(26f + num4, num6, num4, num), cardStyle);
			GUILayout.Label("Last craft", Array.Empty<GUILayoutOption>());
			resultScroll = GUILayout.BeginScrollView(resultScroll, Array.Empty<GUILayoutOption>());
			GUILayout.Label(string.IsNullOrEmpty(message) ? "The changes from your next craft will appear here." : message, Array.Empty<GUILayoutOption>());
			GUILayout.EndScrollView();
			GUILayout.EndArea();
			string text5 = ((!string.IsNullOrEmpty(uiError)) ? uiError : ((target == null) ? "Select an item." : ((!currencySelected) ? "Select a currency." : availability[currency])));
			GUILayout.BeginArea(new Rect(14f, ((Rect)(ref window)).height - num2 - 12f, ((Rect)(ref window)).width - 28f, num2));
			string text6 = ((target == null || !currencySelected) ? "" : (text5 ?? ("Uses one " + CurrencyItems.Name(currency) + ".")));
			if (currencySelected && (int)currency == 8)
			{
				text6 = "<color=#e8b85c>Permanent corruption</color> · " + text6;
			}
			GUILayout.Label(text6, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(Math.Max(18f, num2 - 42f)) });
			GUI.enabled = text5 == null;
			if (GUILayout.Button("Enchant", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) }))
			{
				confirmationJson = plugin.Bridge.Json(target);
				Execute(localPlayer);
			}
			GUI.enabled = true;
			GUILayout.EndArea();
			GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref window)).width - 90f, 25f));
			DrawTooltip();
		}

		private void DrawTooltip()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			if (IsOpen && (int)Event.current.type == 7 && !string.IsNullOrEmpty(hoveredTooltip))
			{
				float num = Math.Min(420f, ((Rect)(ref window)).width - 16f);
				tooltipStyle.fontSize = 14;
				float num2 = tooltipStyle.CalcHeight(new GUIContent(hoveredTooltip), num);
				while (num2 > ((Rect)(ref window)).height - 16f && tooltipStyle.fontSize > 10)
				{
					GUIStyle? obj = tooltipStyle;
					int fontSize = obj.fontSize;
					obj.fontSize = fontSize - 1;
					num2 = tooltipStyle.CalcHeight(new GUIContent(hoveredTooltip), num);
				}
				num2 = Math.Min(num2, ((Rect)(ref window)).height - 16f);
				GUI.Label(new Rect(Math.Max(8f, Math.Min(tooltipMouse.x + 16f, ((Rect)(ref window)).width - num - 8f)), Math.Max(8f, Math.Min(tooltipMouse.y + 20f, ((Rect)(ref window)).height - num2 - 8f)), num, num2), hoveredTooltip, tooltipStyle);
			}
		}

		private bool DrawRow(Rect row, Sprite? icon, string name, string subtitle, string quantity, string tooltip, Color rarity, bool selected, bool dim)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			if (IsHovered(row))
			{
				hoveredTooltip = tooltip;
			}
			bool result = GUI.Button(row, "", (GUIStyle)(selected ? ((object)selectedButton) : ((object)skin.button)));
			GUI.color = (Color)(dim ? new Color(1f, 1f, 1f, 0.45f) : Color.white);
			GUI.DrawTexture(new Rect(((Rect)(ref row)).x + 2f, ((Rect)(ref row)).y + 3f, 3f, ((Rect)(ref row)).height - 6f), (Texture)(object)buttonBackground);
			Color color = GUI.color;
			GUI.color *= rarity;
			GUI.DrawTexture(new Rect(((Rect)(ref row)).x + 2f, ((Rect)(ref row)).y + 3f, 3f, ((Rect)(ref row)).height - 6f), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color;
			DrawIcon(new Rect(((Rect)(ref row)).x + 9f, ((Rect)(ref row)).y + 6f, 32f, 32f), icon);
			float num = (string.IsNullOrEmpty(quantity) ? 20 : 68);
			GUI.Label(new Rect(((Rect)(ref row)).x + 48f, ((Rect)(ref row)).y + (float)((subtitle.Length == 0) ? 9 : 2), Math.Max(10f, ((Rect)(ref row)).width - 48f - num), 24f), name, rowStyle);
			if (subtitle.Length > 0)
			{
				GUI.Label(new Rect(((Rect)(ref row)).x + 48f, ((Rect)(ref row)).y + 25f, Math.Max(10f, ((Rect)(ref row)).width - 48f - num), 17f), subtitle, smallLabel);
			}
			if (quantity.Length > 0)
			{
				GUI.Label(new Rect(((Rect)(ref row)).xMax - 66f, ((Rect)(ref row)).y + 9f, 44f, 24f), quantity, rightLabel);
			}
			GUI.color = Color.white;
			if (selected)
			{
				GUI.Label(new Rect(((Rect)(ref row)).xMax - 20f, ((Rect)(ref row)).y + 10f, 17f, 24f), "✓", rowStyle);
			}
			return result;
		}

		private void SetHoverViewport(float width, float height)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Event.current.type == 7)
			{
				Rect lastRect = GUILayoutUtility.GetLastRect();
				Vector2 val = GUIUtility.GUIToScreenPoint(new Vector2(0f, ((Rect)(ref lastRect)).yMax));
				Vector2 val2 = GUIUtility.GUIToScreenPoint(new Vector2(0f, height));
				hoverViewport = new Rect(val.x, val.y, Math.Max(0f, width - 20f), Math.Max(0f, val2.y - val.y));
			}
		}

		private bool IsHovered(Rect row)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Event.current.type == 7 && ((Rect)(ref row)).Contains(Event.current.mousePosition))
			{
				return ((Rect)(ref hoverViewport)).Contains(GUIUtility.GUIToScreenPoint(Event.current.mousePosition));
			}
			return false;
		}

		private static void DrawIcon(Rect rect, Sprite? sprite)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)sprite) && (int)Event.current.type == 7)
			{
				Vector2[] uv = sprite.uv;
				float num = uv.Min((Vector2 v) => v.x);
				float num2 = uv.Min((Vector2 v) => v.y);
				GUI.DrawTextureWithTexCoords(rect, (Texture)(object)sprite.texture, new Rect(num, num2, uv.Max((Vector2 v) => v.x) - num, uv.Max((Vector2 v) => v.y) - num2));
			}
		}

		private void RefreshUi(Player player, bool force = false)
		{
			//IL_00c5: 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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Expected O, but got Unknown
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			if (!force && Time.unscaledTime < refreshAt)
			{
				return;
			}
			refreshAt = Time.unscaledTime + 0.25f;
			try
			{
				List<ItemData> allItems = ((Humanoid)player).GetInventory().GetAllItems();
				equipment = allItems.Where(Equipment).ToArray();
				if (target != null && !equipment.Contains(target))
				{
					target = null;
				}
				itemTooltips.Clear();
				selectedMagic = ((target == null) ? null : plugin.Bridge.Read(target));
				Currency[] menuOrder = MenuOrder;
				foreach (Currency choice in menuOrder)
				{
					counts[choice] = allItems.Where((ItemData val2) => Object.op_Implicit((Object)(object)val2.m_dropPrefab) && ((Object)val2.m_dropPrefab).name == CurrencyItems.Prefab(choice)).Sum((ItemData val2) => val2.m_stack);
					availability[choice] = ((counts[choice] == 0) ? ("None owned. You need one " + CurrencyItems.Name(choice) + ".") : ((target == null) ? null : Validate(player, choice)));
				}
				if (selectedMagic == null)
				{
					selectedSummary = "Ordinary · 0 effects · 0/3 shard slots";
					selectedDetails = "No enchantment effects.";
				}
				else if ((bool?)selectedMagic["IsUnidentified"] == true)
				{
					selectedSummary = "Unidentified";
					selectedDetails = "Identify this equipment to reveal its enchantments.";
				}
				else
				{
					int num = (int)selectedMagic["Rarity"];
					JArray val = (JArray)selectedMagic["Effects"];
					selectedSummary = CurrencyDropRules.QualityName(num) + " · " + ((JContainer)val).Count + "/" + plugin.Bridge.MaximumEffects(num) + " effects · " + ((int?)selectedMagic["SocketCount"]).GetValueOrDefault() + "/3 shard slots";
					selectedDetails = ((((JContainer)val).Count == 0) ? "No enchantment effects." : string.Join("\n", from e in ((IEnumerable)val).OfType<JObject>()
						select "• " + plugin.Bridge.EffectText(e, selectedMagic)));
					if (CorruptionGuard.IsCorrupted(target))
					{
						selectedDetails += "\n<color=#e8b85c>Corrupted · enchantments locked</color>";
					}
				}
				uiError = "";
			}
			catch (Exception ex)
			{
				if (uiError.Length == 0)
				{
					plugin.LogError(ex.ToString());
				}
				selectedMagic = null;
				selectedSummary = "Unavailable";
				selectedDetails = "Item information unavailable.";
				uiError = "Item information unavailable. See the BepInEx log.";
			}
		}

		private Color RarityColor(int rarity)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (rarity < 0 || rarity > 5)
			{
				return Color.white;
			}
			Color result = default(Color);
			if (!ColorUtility.TryParseHtmlString(plugin.Bridge.Call<string>("GetRarityColorByIndex", new object[1] { rarity }), ref result))
			{
				return Color.white;
			}
			return result;
		}

		private string? Validate(Player player, Currency? choice = null)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Invalid comparison between Unknown and I4
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Invalid comparison between Unknown and I4
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Invalid comparison between Unknown and I4
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Invalid comparison between Unknown and I4
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			if (target == null)
			{
				return "Select an item.";
			}
			if (!choice.HasValue && !currencySelected)
			{
				return "Select a currency.";
			}
			Currency val = (Currency)(((??)choice) ?? currency);
			if (!((Humanoid)player).GetInventory().ContainsItem(target) || !Equipment(target))
			{
				return "The selected item must be unequipped and in your inventory.";
			}
			if (!NearTable(player))
			{
				return "Move closer to the enchanting table.";
			}
			if (CorruptionGuard.NativeUiVisible() || InventoryGui.IsVisible())
			{
				return "Close other crafting windows.";
			}
			if (!plugin.Bridge.Call<bool>("CanBeMagicItem", new object[1] { target }) || plugin.Bridge.Call<bool>("IsUnidentified", new object[1] { target }))
			{
				return "This equipment is not eligible, or must be identified first.";
			}
			if ((int)val == 8 && (!plugin.EnableVaal.Value || !plugin.Guard.Ready))
			{
				return "Experimental Vaal crafting is disabled. See the project playtest guide.";
			}
			if ((int)val == 9 && !IsWeapon(target))
			{
				return "Battle essence requires a weapon.";
			}
			if ((int)val == 10 && IsWeapon(target))
			{
				return "Guard essence requires armour or a shield.";
			}
			JObject val2 = plugin.Bridge.Read(target);
			if ((int)val == 7 && val2 != null && CraftingEngine.HasHistory(val2))
			{
				return "Alchemy requires a base without augment or temper history.";
			}
			string text = plugin.Bridge.Engine(target, random).Validate(val2, CorruptionGuard.IsCorrupted(target), val, GuardEffect(target));
			if (text != null)
			{
				return text;
			}
			if (CurrencyStack(player, val) != null)
			{
				return null;
			}
			return "You need one " + CurrencyItems.Name(val) + " in your inventory.";
		}

		private ItemData? CurrencyStack(Player player, Currency? choice = null)
		{
			return ((IEnumerable<ItemData>)((Humanoid)player).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => i.m_stack > 0 && Object.op_Implicit((Object)(object)i.m_dropPrefab) && ((Object)i.m_dropPrefab).name == CurrencyItems.Prefab((Currency)(((??)choice) ?? currency))));
		}

		private void Execute(Player player)
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			ItemData val = null;
			ItemData val2 = null;
			Inventory inventory = ((Humanoid)player).GetInventory();
			try
			{
				string text = Validate(player);
				if (text != null)
				{
					throw new InvalidOperationException(text);
				}
				if (plugin.Bridge.Json(target) != confirmationJson)
				{
					throw new InvalidOperationException("The item changed after confirmation. Select it again.");
				}
				ItemData val3 = target;
				JObject val4 = plugin.Bridge.Read(val3);
				CraftResult val5 = plugin.Bridge.Engine(val3, random).Prepare(val4, false, currency, GuardEffect(val3), (int?)null);
				string text2 = CraftFeedback.Describe(val4, val5.ApplyMagic ? val5.Magic : val4, (Func<JObject, JObject, string>)plugin.Bridge.EffectText, val5.Corrupted);
				ItemData val6 = CurrencyStack(player);
				val = val3.Clone();
				val2 = val6.Clone();
				val2.m_stack = 1;
				if (!inventory.RemoveItem(val6, 1))
				{
					throw new InvalidOperationException("The currency could not be consumed.");
				}
				flag = true;
				if (val5.ApplyMagic && !plugin.Bridge.Apply(val3, val5.Magic))
				{
					throw new InvalidOperationException("Epic Loot rejected the prepared item.");
				}
				if (val5.Corrupted)
				{
					CorruptionGuard.Mark(val3);
				}
				plugin.Bridge.Invalidate(player);
				message = CurrencyItems.Name(currency) + " · " + Localization.instance.Localize(val3.m_shared.m_name) + "\n" + text2;
				itemTooltips.Remove(val3);
				resultScroll = Vector2.zero;
				RefreshUi(player, force: true);
			}
			catch (Exception ex)
			{
				if (flag && val != null && val2 != null)
				{
					if (target != null && inventory.ContainsItem(target) && inventory.RemoveItem(target))
					{
						if (!inventory.AddItem(val, val.m_gridPos))
						{
							plugin.LogError("Could not restore the target item: " + val.m_shared.m_name);
						}
						target = null;
					}
					else
					{
						plugin.LogError("Craft rollback could not find the target item. Preserve this log and the character backup.");
					}
					if (!inventory.AddItem(val2))
					{
						plugin.LogError("Could not refund currency: " + val2.m_shared.m_name);
					}
				}
				plugin.LogError("Currency craft failed: " + ex);
				message = "Craft cancelled: " + ex.Message;
			}
		}

		static CraftingPanel()
		{
			Currency[] array = new Currency[16];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			MenuOrder = (Currency[])(object)array;
		}
	}
	internal sealed class CurrencyDrops
	{
		private readonly Dictionary<Currency, ConfigEntry<float>> chances = new Dictionary<Currency, ConfigEntry<float>>();

		private readonly ConfigEntry<bool> enabled;

		private readonly MethodInfo spawn;

		private readonly Plugin plugin;

		internal CurrencyDrops(Plugin plugin, Harmony harmony)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			this.plugin = plugin;
			enabled = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Drops", "Enabled", true, new ConfigDescription("Add currencies alongside Epic Loot equipment and material drops.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			foreach (Currency value in Enum.GetValues(typeof(Currency)))
			{
				chances[value] = ((BaseUnityPlugin)plugin).Config.Bind<float>("Drops", ((object)value/*cast due to .constrained prefix*/).ToString() + "ChancePercent", CurrencyDropRules.DefaultChance(value), new ConfigDescription("Independent percent chance for one " + CurrencyItems.Name(value) + " when an Epic Loot drop batch contains " + CurrencyDropRules.MinimumQualityName(value) + " or higher-quality equipment or crafting materials. Rolled once per eligible batch, regardless of stack size or number of items. 0 disables this drop; 100 guarantees it on eligible batches. Vaal also requires EnableVaal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { (object)new ConfigurationManagerAttributes
				{
					IsAdminOnly = true
				} }));
			}
			Type type = Type.GetType("EpicLoot.LootRoller, EpicLoot", throwOnError: true);
			spawn = type.GetMethod("SpawnLootForDrop", BindingFlags.Static | BindingFlags.Public);
			Type type2 = Type.GetType("EpicLoot.EpicLootDropsHelper, EpicLoot", throwOnError: true);
			harmony.Patch((MethodBase)type2.GetMethod("DropItems", BindingFlags.Static | BindingFlags.Public), new HarmonyMethod(typeof(CurrencyDrops), "BeforeDropItems", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void BeforeDropItems(List<GameObject> loot, Vector3 centerPos)
		{
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Invalid comparison between Unknown and I4
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected O, but got Unknown
			CurrencyDrops drops = Plugin.Instance.Drops;
			if (drops == null || !drops.enabled.Value || loot == null || !Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				return;
			}
			try
			{
				int num = -1;
				foreach (GameObject item2 in loot)
				{
					if (!Object.op_Implicit((Object)(object)item2))
					{
						continue;
					}
					ItemData val = item2.GetComponent<ItemDrop>()?.m_itemData;
					if (!((Object)(object)val?.m_dropPrefab == (Object)null) && val.m_stack > 0 && !((Object)val.m_dropPrefab).name.StartsWith("POEC_", StringComparison.Ordinal))
					{
						int num2 = CurrencyDropRules.MaterialQuality(((Object)val.m_dropPrefab).name);
						if (num2 < 0)
						{
							num2 = drops.plugin.Bridge.Rarity(val);
						}
						if (num2 >= 0 && num2 <= 5)
						{
							num = Math.Max(num, num2);
						}
					}
				}
				foreach (Currency value2 in Enum.GetValues(typeof(Currency)))
				{
					if (!CurrencyDropRules.Eligible(value2, num) || ((int)value2 == 8 && (!drops.plugin.EnableVaal.Value || !drops.plugin.Guard.Ready)))
					{
						continue;
					}
					float value = drops.chances[value2].Value;
					if (!(value <= 0f))
					{
						GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(CurrencyItems.Prefab(value2));
						if (Object.op_Implicit((Object)(object)itemPrefab) && CurrencyDropRules.ShouldDrop(value, (double)Random.Range(0, int.MaxValue) / 2147483647.0))
						{
							GameObject item = (GameObject)drops.spawn.Invoke(null, new object[3] { itemPrefab, centerPos, true });
							loot.Add(item);
						}
					}
				}
			}
			catch (Exception ex)
			{
				drops.plugin.LogError("Currency bonus drops failed; original Epic Loot drops retained: " + ex);
			}
		}
	}
	public sealed class CurrencyGlow : MonoBehaviour
	{
		[SerializeField]
		internal Currency Currency;

		private GameObject? beam;

		private readonly List<Material> ownedMaterials = new List<Material>();

		private static bool warned;

		private void Start()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			if ((int)SystemInfo.graphicsDeviceType == 4)
			{
				return;
			}
			try
			{
				GameObject[] array = (GameObject[])Type.GetType("EpicLoot.EpicAssets, EpicLoot", throwOnError: true).GetField("MagicItemLootBeamPrefabs", BindingFlags.Static | BindingFlags.Public).GetValue(null);
				int num = CurrencyDropRules.VisualQuality(Currency);
				if (num >= array.Length || !Object.op_Implicit((Object)(object)array[num]))
				{
					throw new InvalidOperationException("Epic Loot material beam is unavailable.");
				}
				beam = Object.Instantiate<GameObject>(array[num], ((Component)this).transform);
				beam.transform.localPosition = Vector3.up * 0.01f;
				Renderer[] componentsInChildren = beam.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val in componentsInChildren)
				{
					Material[] sharedMaterials = val.sharedMaterials;
					for (int j = 0; j < sharedMaterials.Length; j++)
					{
						if (Object.op_Implicit((Object)(object)sharedMaterials[j]))
						{
							sharedMaterials[j] = new Material(sharedMaterials[j]);
							ownedMaterials.Add(sharedMaterials[j]);
						}
					}
					val.sharedMaterials = sharedMaterials;
				}
				Type type = Type.GetType("EpicLoot.LootBeams.BeamColorSetter, EpicLoot", throwOnError: true);
				Component obj = beam.GetComponent(type) ?? beam.AddComponent(type);
				Color val2 = (Color)(num switch
				{
					2 => new Color(0.9f, 0.2f, 0.3f), 
					3 => new Color(1f, 0.55f, 0.15f), 
					0 => new Color(0.3f, 0.65f, 1f), 
					_ => new Color(1f, 0.85f, 0.25f), 
				});
				type.GetMethod("SetColor").Invoke(obj, new object[1] { val2 });
				AudioSource[] componentsInChildren2 = beam.GetComponentsInChildren<AudioSource>(true);
				foreach (AudioSource obj2 in componentsInChildren2)
				{
					obj2.Stop();
					((Behaviour)obj2).enabled = false;
				}
				Animator component = beam.GetComponent<Animator>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.Play("Show");
				}
			}
			catch (Exception ex)
			{
				if (Object.op_Implicit((Object)(object)beam))
				{
					Object.Destroy((Object)(object)beam);
				}
				ReleaseMaterials();
				if (!warned)
				{
					warned = true;
					Logger.LogWarning((object)("Currency glow unavailable: " + ex.Message));
				}
			}
		}

		private void LateUpdate()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)beam))
			{
				beam.transform.rotation = Quaternion.identity;
			}
		}

		private void OnDestroy()
		{
			ReleaseMaterials();
		}

		private void ReleaseMaterials()
		{
			foreach (Material ownedMaterial in ownedMaterials)
			{
				if (Object.op_Implicit((Object)(object)ownedMaterial))
				{
					Object.Destroy((Object)(object)ownedMaterial);
				}
			}
			ownedMaterials.Clear();
		}
	}
	internal static class CurrencyIcons
	{
		internal unsafe static Sprite Load(Currency currency)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			string text = "POECrafting.Icons." + ((object)(*(Currency*)(&currency))/*cast due to .constrained prefix*/).ToString() + ".png";
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text) ?? throw new InvalidOperationException("Missing currency icon: " + text);
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			((Object)val).name = CurrencyItems.Prefab(currency) + "_Icon";
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			if (!AssetUtils.LoadImage(val, memoryStream.ToArray()))
			{
				Object.Destroy((Object)(object)val);
				throw new InvalidOperationException("Cannot decode currency icon: " + text);
			}
			val.Apply(false, true);
			Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), (float)((Texture)val).width);
			((Object)obj).name = ((Object)val).name;
			return obj;
		}
	}
	internal static class CurrencyItems
	{
		internal unsafe static string Prefab(Currency currency)
		{
			return "POEC_" + ((object)(*(Currency*)(&currency))/*cast due to .constrained prefix*/).ToString();
		}

		private static bool IsEssence(Currency currency)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)currency >= 9)
			{
				return (int)currency <= 13;
			}
			return false;
		}

		internal unsafe static string Name(Currency currency)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected I4, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Invalid comparison between Unknown and I4
			if (IsEssence(currency))
			{
				return "Essence of " + ((object)(*(Currency*)(&currency))/*cast due to .constrained prefix*/).ToString();
			}
			string result;
			switch (currency - 2)
			{
			default:
				if ((int)currency != 14)
				{
					if ((int)currency != 15)
					{
						goto case 4;
					}
					result = "Perfect Exalted Orb";
					break;
				}
				result = "Gemcutter's Prism";
				break;
			case 0:
				result = "Regal Orb";
				break;
			case 1:
				result = "Exalted Orb";
				break;
			case 2:
				result = "Chaos Orb";
				break;
			case 3:
				result = "Divine Orb";
				break;
			case 6:
				result = "Vaal Orb";
				break;
			case 4:
			case 5:
				result = "Orb of " + ((object)(*(Currency*)(&currency))/*cast due to .constrained prefix*/).ToString();
				break;
			}
			return result;
		}

		internal static string Description(Currency currency)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected I4, but got Unknown
			return (int)currency switch
			{
				0 => "Ordinary equipment becomes Magic with one random effect.", 
				1 => "Add one random effect to Magic equipment. Limit: two effects.", 
				2 => "Upgrade Magic equipment to Rare, keeping its rolls and adding one effect.", 
				3 => "Add one random eligible effect to Magic through Legendary equipment. Full Rare/Epic gear upgrades to the next tier with room, up to Legendary. Magic stays Magic. Mythic and Ancient require Perfect Exalted. Existing effects and sockets stay.", 
				15 => "Add one random eligible effect. If this rarity is full, upgrade to the next rarity with room, up to Ancient. Uses Epic Loot's live effect limits. Existing effects and sockets stay.", 
				4 => "Replace one random eligible effect on enchanted equipment of any rarity. Other effects, rarity and sockets stay. Protected effects are preserved.", 
				5 => "Reroll eligible, untempered numerical effects on enchanted equipment of any rarity. Rolls can improve or worsen. Rarity, sockets and protected effects stay.", 
				6 => "Remove one random eligible effect on enchanted equipment of any rarity, including augmented gear. Costs only one orb. This can remove an effect you wanted to keep. Protected effects stay.", 
				7 => "Create Rare equipment with four random effects. Existing effects are replaced; used augment/temper bases are protected.", 
				8 => "Permanently corrupt equipment of any rarity: no change, an extra effect, value rerolls, or replacement effects. Ordinary gear gains Magic quality only if an effect is added. It cannot be enchanted again. No destruction outcome in this prototype.", 
				9 => "Upgrade Magic equipment to Rare, adding guaranteed physical damage on eligible weapons.", 
				10 => "Upgrade Magic equipment to Rare, adding guaranteed armour or shield block power.", 
				11 => "Upgrade Magic equipment to Rare, adding guaranteed maximum health.", 
				12 => "Upgrade Magic equipment to Rare, adding guaranteed maximum stamina.", 
				13 => "Upgrade Magic equipment to Rare, adding guaranteed maximum eitr on eligible equipment.", 
				14 => "Add one Epic Loot shard slot to equipment of any rarity, up to three slots. Existing shards and effects are preserved. Ordinary gear becomes Magic with no random effects. Corrupted gear cannot gain slots.", 
				_ => throw new ArgumentOutOfRangeException("currency"), 
			};
		}

		internal static void Register(bool recipes)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Invalid comparison between Unknown and I4
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Invalid comparison between Unknown and I4
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			foreach (Currency value in Enum.GetValues(typeof(Currency)))
			{
				ItemConfig val2 = new ItemConfig
				{
					Name = Name(value),
					Description = Description(value) + " Use POE Crafting at an enchanting table, or press F8 nearby.",
					StackSize = 999,
					Weight = 0f,
					Enabled = recipes,
					Amount = 1,
					CraftingStation = (((int)value <= 1) ? "piece_workbench" : "forge"),
					MinStationLevel = 1,
					Requirements = Requirements(value),
					Icon = CurrencyIcons.Load(value)
				};
				CustomItem val3 = new CustomItem(Prefab(value), (IsEssence(value) || (int)value == 14) ? "Crystal" : "AmberPearl", val2);
				val3.ItemPrefab.AddComponent<CurrencyGlow>().Currency = value;
				ItemData itemData = val3.ItemPrefab.GetComponent<ItemDrop>().m_itemData;
				string text = "local.valheim.poecrafting." + ((object)value/*cast due to .constrained prefix*/).ToString();
				itemData.m_shared.m_ammoType = text;
				if (!ItemManager.Instance.AddItem(val3))
				{
					throw new InvalidOperationException("Could not register " + Prefab(value));
				}
				if (string.IsNullOrEmpty(Plugin.Instance.Bridge.Call<string>("AddSacrifice", new object[1] { ((JToken)CurrencyMaterials.SacrificeDefinition(value, itemData.m_shared.m_name, text)).ToString((Formatting)0, Array.Empty<JsonConverter>()) })))
				{
					throw new InvalidOperationException("Epic Loot rejected sacrifice registration for " + Prefab(value));
				}
			}
		}

		private static RequirementConfig[] Requirements(Currency currency)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected I4, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Expected O, but got Unknown
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Expected O, but got Unknown
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			List<RequirementConfig> list = new List<RequirementConfig>();
			string text = CurrencyMaterials.Dust(currency);
			string text2 = CurrencyMaterials.Essence(currency);
			list.Add(new RequirementConfig(text, ((int)currency == 5 || (int)currency == 8 || (int)currency == 15) ? 10 : 3, 0, true));
			list.Add(new RequirementConfig(text2, ((int)currency == 5 || (int)currency == 8 || (int)currency == 15) ? 10 : 3, 0, true));
			switch (currency - 2)
			{
			case 0:
				list.Add(new RequirementConfig("Bronze", 1, 0, true));
				break;
			case 1:
			case 5:
			case 13:
				list.Add(new RequirementConfig("Iron", 1, 0, true));
				break;
			case 2:
			case 4:
				list.Add(new RequirementConfig("Obsidian", 2, 0, true));
				break;
			case 3:
				list.Add(new RequirementConfig("Silver", 2, 0, true));
				break;
			case 6:
				list.Add(new RequirementConfig("BlackMetal", 2, 0, true));
				break;
			case 7:
				list.Add(new RequirementConfig("Iron", 1, 0, true));
				break;
			case 8:
				list.Add(new RequirementConfig("Bronze", 1, 0, true));
				break;
			case 9:
				list.Add(new RequirementConfig("Bloodbag", 2, 0, true));
				break;
			case 10:
				list.Add(new RequirementConfig("Honey", 4, 0, true));
				break;
			case 11:
				list.Add(new RequirementConfig("Eitr", 1, 0, true));
				break;
			case 12:
				list.Add(new RequirementConfig("Crystal", 1, 0, true));
				break;
			}
			return list.ToArray();
		}
	}
	internal sealed class EnchanterButton
	{
		private readonly PropertyInfo instance;

		private readonly FieldInfo root;

		private readonly FieldInfo tabScrim;

		private readonly MethodInfo hide;

		private GameObject? buttonObject;

		private Button? button;

		internal EnchanterButton(EpicLootBridge bridge)
		{
			Type type = bridge.ApiType.Assembly.GetType("EpicLoot_UnityLib.EnchantingTableUI", throwOnError: true);
			instance = AccessTools.Property(type, "instance") ?? throw new MissingMemberException(type.FullName, "instance");
			root = AccessTools.Field(type, "Root") ?? throw new MissingFieldException(type.FullName, "Root");
			tabScrim = AccessTools.Field(type, "TabScrim") ?? throw new MissingFieldException(type.FullName, "TabScrim");
			hide = AccessTools.Method(type, "Hide", (Type[])null, (Type[])null) ?? throw new MissingMethodException(type.FullName, "Hide");
		}

		internal void Update()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			object value = instance.GetValue(null, null);
			if (value == null)
			{
				return;
			}
			object? value2 = root.GetValue(value);
			GameObject val = (GameObject)((value2 is GameObject) ? value2 : null);
			if (val != null && val.activeInHierarchy)
			{
				if (!Object.op_Implicit((Object)(object)buttonObject) || (Object)(object)buttonObject.transform.parent != (Object)(object)val.transform)
				{
					Dispose();
					buttonObject = GUIManager.Instance.CreateButton("POE Crafting", val.transform, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(106f, 24f), 180f, 34f);
					((Object)buttonObject).name = "POECraftingButton";
					button = buttonObject.GetComponent<Button>();
					((UnityEvent)button.onClick).AddListener(new UnityAction(Open));
				}
				Button? obj = button;
				object? value3 = tabScrim.GetValue(value);
				GameObject val2 = (GameObject)((value3 is GameObject) ? value3 : null);
				((Selectable)obj).interactable = val2 == null || !val2.activeSelf;
			}
		}

		private void Open()
		{
			object value = instance.GetValue(null, null);
			if (value != null)
			{
				object? value2 = tabScrim.GetValue(value);
				GameObject val = (GameObject)((value2 is GameObject) ? value2 : null);
				if (val == null || !val.activeSelf)
				{
					hide.Invoke(null, null);
					Plugin.Instance.Panel.OpenFromTable();
				}
			}
		}

		internal void Dispose()
		{
			if (Object.op_Implicit((Object)(object)buttonObject))
			{
				Object.Destroy((Object)(object)buttonObject);
			}
			buttonObject = null;
			button = null;
		}
	}
	internal sealed class EpicLootBridge
	{
		internal readonly Type ApiType;

		private readonly Dictionary<string, MethodInfo> methods = new Dictionary<string, MethodInfo>();

		private readonly MethodInfo effectCounts;

		private readonly ConstructorInfo effectConstructor;

		private readonly MethodInfo effectText;

		internal string Version => Call<string>("GetPluginVersion", Array.Empty<object>());

		internal EpicLootBridge()
		{
			ApiType = Type.GetType("EpicLoot.API, EpicLoot", throwOnError: true);
			Type type = ApiType.Assembly.GetType("EpicLoot.LootRoller", throwOnError: true);
			effectCounts = type.GetMethod("GetEffectCountsPerRarity", BindingFlags.Static | BindingFlags.Public) ?? throw new MissingMethodException(type.FullName, "GetEffectCountsPerRarity");
			Type effectType = ApiType.Assembly.GetType("EpicLoot.MagicItemEffect", throwOnError: true);
			effectConstructor = effectType.GetConstructor(new Type[2]
			{
				typeof(string),
				typeof(float)
			}) ?? throw new MissingMethodException(effectType.FullName, ".ctor");
			effectText = ApiType.Assembly.GetType("EpicLoot.MagicItem", throwOnError: true).GetMethods(BindingFlags.Static | BindingFlags.Public).Single((MethodInfo m) => m.Name == "GetEffectText" && m.GetParameters().Length == 4 && m.GetParameters()[0].ParameterType == effectType);
			string[] array = new string[11]
			{
				"GetPluginVersion", "GetMagicItemJson", "ApplyMagicItemJson", "GetAvailableEffectTypes", "GetMagicItemEffectDefinition", "CanBeMagicItem", "IsUnidentified", "InvalidatePlayerEffectCache", "TryGetRarity", "GetRarityColorByIndex",
				"AddSacrifice"
			};
			foreach (string text in array)
			{
				methods[text] = ApiType.GetMethod(text, BindingFlags.Static | BindingFlags.Public) ?? throw new InvalidOperationException("Epic Loot API endpoint missing: " + text);
			}
		}

		internal T Call<T>(string name, params object[] args)
		{
			return (T)methods[name].Invoke(null, args);
		}

		internal string Json(ItemData item)
		{
			return Call<string>("GetMagicItemJson", new object[1] { item });
		}

		internal int Rarity(ItemData item)
		{
			object[] array = new object[2] { item, -1 };
			if (!Call<bool>("TryGetRarity", array))
			{
				return -1;
			}
			return (int)array[1];
		}

		internal JObject? Read(ItemData item)
		{
			string text = Json(item);
			if (!string.IsNullOrWhiteSpace(text))
			{
				return JObject.Parse(text);
			}
			return null;
		}

		internal bool Apply(ItemData item, JObject magic)
		{
			return Call<bool>("ApplyMagicItemJson", new object[2]
			{
				item,
				((JToken)magic).ToString((Formatting)0, Array.Empty<JsonConverter>())
			});
		}

		internal EffectDefinition? Definition(string type, int rarity)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			if (rarity < 0 || rarity > 5)
			{
				return null;
			}
			string text = Call<string>("GetMagicItemEffectDefinition", new object[1] { type });
			if (string.IsNullOrWhiteSpace(text))
			{
				return null;
			}
			JObject val = JObject.Parse(text);
			JToken obj = val["ValuesPerRarity"];
			JToken obj2 = ((obj != null) ? obj[(object)CurrencyDropRules.QualityName(rarity)] : null);
			JObject val2 = (JObject)(object)((obj2 is JObject) ? obj2 : null);
			EffectDefinition val3 = new EffectDefinition
			{
				Type = type,
				Weight = (((double?)val["SelectionWeight"]) ?? 1.0)
			};
			int mutable;
			if (((bool?)val["CanBeAugmented"]) ?? true)
			{
				JToken obj3 = val["Requirements"];
				mutable = (((bool?)((obj3 != null) ? obj3[(object)"NoRoll"] : null) != true) ? 1 : 0);
			}
			else
			{
				mutable = 0;
			}
			val3.Mutable = (byte)mutable != 0;
			val3.Min = (double?)((val2 != null) ? val2["MinValue"] : null);
			val3.Max = (double?)((val2 != null) ? val2["MaxValue"] : null);
			val3.Increment = ((double?)((val2 != null) ? val2["Increment"] : null)).GetValueOrDefault();
			return val3;
		}

		internal IReadOnlyList<EffectDefinition> Available(ItemData item, JObject magic)
		{
			int rarity = (int)magic["Rarity"];
			return (from t in Call<List<string>>("GetAvailableEffectTypes", new object[3]
				{
					item,
					((JToken)magic).ToString((Formatting)0, Array.Empty<JsonConverter>()),
					rarity
				}).Distinct()
				select Definition(t, rarity) into d
				where d != null
				select d).Cast<EffectDefinition>().ToList();
		}

		internal int MaximumEffects(int rarity)
		{
			if (rarity < 0 || rarity > 5)
			{
				throw new ArgumentOutOfRangeException("rarity");
			}
			object obj = Enum.ToObject(effectCounts.GetParameters()[0].ParameterType, rarity);
			return CraftingEngine.MaximumEffectCount((IEnumerable<KeyValuePair<int, float>>)effectCounts.Invoke(null, new object[2] { obj, false }));
		}

		internal CraftingEngine Engine(ItemData item, Random random)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			return new CraftingEngine((Func<JObject, IReadOnlyList<EffectDefinition>>)((JObject magic) => Available(item, magic)), (Func<string, int, EffectDefinition>)Definition, (Func<double>)random.NextDouble, (Func<int, int>)MaximumEffects);
		}

		internal string EffectText(JObject effect, JObject magic)
		{
			string text = ((string)effect["EffectType"]) ?? "UnknownEffect";
			try
			{
				object obj = effectConstructor.Invoke(new object[2]
				{
					text,
					((float?)effect["EffectValue"]) ?? 1f
				});
				object obj2 = Enum.ToObject(effectText.GetParameters()[1].ParameterType, ((int?)magic["Rarity"]).GetValueOrDefault());
				return (string)effectText.Invoke(null, new object[4]
				{
					obj,
					obj2,
					false,
					(string)magic["LegendaryID"]
				});
			}
			catch
			{
				return Regex.Replace(text, "(?<=[a-z])(?=[A-Z])", " ") + ": " + (object)effect["EffectValue"];
			}
		}

		internal void Invalidate(Player player)
		{
			methods["InvalidatePlayerEffectCache"].Invoke(null, new object[1] { player });
		}
	}
	[BepInPlugin("local.valheim.poecrafting", "POE Crafting", "0.1.8")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "local.valheim.poecrafting";

		public const string Version = "0.1.8";

		internal static Plugin Instance;

		internal EpicLootBridge Bridge;

		internal CorruptionGuard Guard;

		internal CraftingPanel Panel;

		internal CurrencyDrops Drops;

		private EnchanterButton tableButton;

		internal ConfigEntry<bool> EnableVaal;

		internal ConfigEntry<KeyCode> OpenKey;

		private ConfigEntry<bool> recipes;

		private Harmony harmony;

		private void Awake()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			Instance = this;
			OpenKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Interface", "OpenKey", (KeyCode)289, "Open currency crafting near an Epic Loot enchanting table.");
			recipes = ((BaseUnityPlugin)this).Config.Bind<bool>("Crafting", "EnableRecipes", true, new ConfigDescription("Register provisional orb and essence recipes. Requires restart.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			EnableVaal = ((BaseUnityPlugin)this).Config.Bind<bool>("Crafting", "EnableVaal", false, new ConfigDescription("Enable experimental Vaal crafting after testing a backed-up character. Corruption protection is always active.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			try
			{
				Bridge = new EpicLootBridge();
				harmony = new Harmony("local.valheim.poecrafting");
				Guard = new CorruptionGuard(harmony, Bridge);
				Drops = new CurrencyDrops(this, harmony);
				Panel = new CraftingPanel(this);
				tableButton = new EnchanterButton(Bridge);
				PrefabManager.OnVanillaPrefabsAvailable += RegisterItems;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("POE Crafting prototype ready. Epic Loot " + Bridge.Version + "; corruption guards: " + Guard.Ready));
				if (!Guard.Ready)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Vaal crafting is unavailable: this Epic Loot version has not passed the corruption-hook checks.");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("POE Crafting disabled: " + ex));
				((Behaviour)this).enabled = false;
			}
		}

		private void RegisterItems()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterItems;
			try
			{
				CurrencyItems.Register(recipes.Value);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Currency registration failed: " + ex));
				((Behaviour)this).enabled = false;
			}
		}

		private void Update()
		{
			tableButton?.Update();
			Panel?.Update();
		}

		private void OnGUI()
		{
			Panel?.Draw();
		}

		private void OnDisable()
		{
			Panel?.Close();
			tableButton?.Dispose();
		}

		private void OnDestroy()
		{
			Panel?.Dispose();
			tableButton?.Dispose();
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterItems;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		internal void LogError(string message)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)message);
		}
	}
}

plugins/POECrafting/POECrafting.Core.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json.Linq;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("POECrafting.Core")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("POECrafting.Core")]
[assembly: AssemblyTitle("POECrafting.Core")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace POECrafting.Core
{
	public static class CraftFeedback
	{
		public static string Describe(JObject? before, JObject? after, Func<JObject, JObject, string> format, bool corrupted)
		{
			List<string> list = new List<string>();
			int num = ((int?)((before != null) ? before["Rarity"] : null)) ?? (-1);
			int num2 = ((int?)((after != null) ? after["Rarity"] : null)) ?? (-1);
			if (num != num2)
			{
				list.Add("Rarity: " + Quality(num) + " → " + Quality(num2));
			}
			int valueOrDefault = ((int?)((before != null) ? before["SocketCount"] : null)).GetValueOrDefault();
			int valueOrDefault2 = ((int?)((after != null) ? after["SocketCount"] : null)).GetValueOrDefault();
			if (valueOrDefault != valueOrDefault2)
			{
				list.Add("Shard slots: " + valueOrDefault + " → " + valueOrDefault2);
			}
			JToken obj = ((before != null) ? before["Effects"] : null);
			List<JObject> list2 = ((IEnumerable)((obj is JArray) ? obj : null))?.OfType<JObject>().ToList() ?? new List<JObject>();
			List<JObject> list3 = new List<JObject>();
			JToken obj2 = ((after != null) ? after["Effects"] : null);
			foreach (JObject effect in ((IEnumerable)((obj2 is JArray) ? obj2 : null))?.OfType<JObject>() ?? Enumerable.Empty<JObject>())
			{
				JObject val = ((IEnumerable<JObject>)list2).FirstOrDefault((Func<JObject, bool>)((JObject e) => (string)e["EffectType"] == (string)effect["EffectType"] && SameValue(e["EffectValue"], effect["EffectValue"])));
				if (val != null)
				{
					list2.Remove(val);
				}
				else
				{
					list3.Add(effect);
				}
			}
			foreach (JObject effect2 in list3)
			{
				JObject val2 = ((IEnumerable<JObject>)list2).FirstOrDefault((Func<JObject, bool>)((JObject e) => (string)e["EffectType"] == (string)effect2["EffectType"]));
				if (val2 == null)
				{
					list.Add("Added: " + format(effect2, after));
					continue;
				}
				list.Add("Rerolled: " + format(val2, before) + " → " + format(effect2, after));
				list2.Remove(val2);
			}
			foreach (JObject item in list2)
			{
				list.Add("Removed: " + format(item, before));
			}
			if (list.Count == 0)
			{
				list.Add("No effects changed.");
			}
			if (corrupted)
			{
				list.Add("Permanently corrupted. Further currency crafting is locked.");
			}
			return string.Join("\n", list);
		}

		private static string Quality(int rarity)
		{
			if (rarity >= 0)
			{
				return CurrencyDropRules.QualityName(rarity);
			}
			return "Ordinary";
		}

		private static bool SameValue(JToken? left, JToken? right)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			if (left == null || right == null || ((int)left.Type != 7 && (int)left.Type != 6) || ((int)right.Type != 7 && (int)right.Type != 6))
			{
				return JToken.DeepEquals(left, right);
			}
			return (double)left == (double)right;
		}
	}
	public enum Currency
	{
		Transmutation,
		Augmentation,
		Regal,
		Exalted,
		Chaos,
		Divine,
		Annulment,
		Alchemy,
		Vaal,
		Battle,
		Guard,
		Vitality,
		Vigor,
		Sorcery,
		GemcuttersPrism,
		PerfectExalted
	}
	public sealed class EffectDefinition
	{
		public string Type = "";

		public double Weight = 1.0;

		public bool Mutable = true;

		public double? Min;

		public double? Max;

		public double Increment;
	}
	public sealed class CraftResult
	{
		public JObject Magic = new JObject();

		public bool ApplyMagic = true;

		public bool Corrupted;

		public string Outcome = "";
	}
	public sealed class CraftingEngine
	{
		private readonly Func<JObject, IReadOnlyList<EffectDefinition>> available;

		private readonly Func<string, int, EffectDefinition?> definition;

		private readonly Func<double> random;

		private readonly Func<int, int> maximumEffects;

		public CraftingEngine(Func<JObject, IReadOnlyList<EffectDefinition>> available, Func<string, int, EffectDefinition?> definition, Func<double> random, Func<int, int>? maximumEffects = null)
		{
			this.available = available;
			this.definition = definition;
			this.random = random;
			this.maximumEffects = maximumEffects ?? ((Func<int, int>)delegate
			{
				throw new InvalidOperationException("Epic Loot's effect limit is unavailable.");
			});
		}

		public string? Validate(JObject? magic, bool corrupted, Currency currency, string guardEffect = "ModifyArmor")
		{
			if (corrupted)
			{
				return "Corrupted items cannot be currency crafted.";
			}
			if (magic == null)
			{
				if (currency != Currency.Transmutation && currency != Currency.Alchemy && currency != Currency.Vaal && currency != Currency.GemcuttersPrism)
				{
					return "This currency requires enchanted equipment.";
				}
				return null;
			}
			int rarity = ((int?)magic["Rarity"]) ?? (-1);
			bool flag = currency == Currency.Vaal || currency == Currency.GemcuttersPrism || currency == Currency.Chaos || currency == Currency.Divine || currency == Currency.Annulment || currency == Currency.Exalted || currency == Currency.PerfectExalted;
			if (rarity < 0 || rarity > ((!flag) ? 1 : 5))
			{
				return "This equipment rarity is not supported by this currency.";
			}
			if ((bool?)magic["IsUnidentified"] == true)
			{
				return "Identify this item first.";
			}
			if (currency == Currency.GemcuttersPrism)
			{
				int valueOrDefault = ((int?)magic["SocketCount"]).GetValueOrDefault();
				if (valueOrDefault >= 0)
				{
					JToken obj = magic["Sockets"];
					JArray val = (JArray)(object)((obj is JArray) ? obj : null);
					if (val != null && ((JContainer)val).Count <= valueOrDefault)
					{
						if (valueOrDefault < 3)
						{
							return null;
						}
						return "This item already has three or more shard slots.";
					}
				}
				return "Invalid shard slot data.";
			}
			JToken obj2 = magic["Effects"];
			JArray val2 = (JArray)(object)((obj2 is JArray) ? obj2 : null);
			if (val2 == null || ((IEnumerable<JToken>)val2).Any((JToken e) => !(e is JObject) || string.IsNullOrEmpty((string)e[(object)"EffectType"])))
			{
				return "Invalid Epic Loot effect data.";
			}
			switch (currency)
			{
			case Currency.Vaal:
				return null;
			case Currency.Exalted:
			case Currency.PerfectExalted:
			{
				if (currency == Currency.Exalted && rarity > 3)
				{
					return "Regular Exalted Orbs support Magic through Legendary. Use a Perfect Exalted Orb for Mythic or Ancient equipment.";
				}
				int ceiling = ((currency == Currency.PerfectExalted) ? 5 : ((rarity != 0) ? 3 : 0));
				if (ExaltedRarity(rarity, ((JContainer)val2).Count, ceiling) >= 0)
				{
					return null;
				}
				return "This item has reached the maximum effect capacity allowed by this orb.";
			}
			case Currency.Chaos:
				if (MutableIndices(magic).Count != 0)
				{
					return null;
				}
				return "There is no eligible effect to replace.";
			case Currency.Divine:
				if (DivineTargets(magic).Count != 0)
				{
					return null;
				}
				return "There are no untempered numerical rolls to reroll.";
			case Currency.Annulment:
				if (MutableIndices(magic).Count != 0)
				{
					return null;
				}
				return "There is no eligible effect to remove.";
			default:
				if (!string.IsNullOrEmpty((string)magic["LegendaryID"]) || !string.IsNullOrEmpty((string)magic["SetID"]) || !string.IsNullOrEmpty((string)magic["TypeNameOverride"]))
				{
					return "Special and set items are protected.";
				}
				if (((JContainer)val2).Count > ((rarity == 0) ? 2 : 4))
				{
					return "This item already exceeds the currency crafting limit.";
				}
				if (((IEnumerable<JToken>)val2).Any((JToken e) => !(definition((string)e[(object)"EffectType"], rarity)?.Mutable ?? false)))
				{
					return "This item has protected or unsupported effects.";
				}
				switch (currency)
				{
				case Currency.Transmutation:
					return "Transmutation requires ordinary equipment.";
				case Currency.Augmentation:
					if (rarity == 0)
					{
						if (((JContainer)val2).Count < 2)
						{
							return null;
						}
						return "Magic equipment already has two effects.";
					}
					return "Augmentation requires Magic equipment.";
				case Currency.Regal:
				case Currency.Battle:
				case Currency.Guard:
				case Currency.Vitality:
				case Currency.Vigor:
				case Currency.Sorcery:
					if (rarity != 0)
					{
						return "This currency upgrades Magic equipment to Rare.";
					}
					return null;
				case Currency.Alchemy:
					if (rarity != 0)
					{
						return "Alchemy requires ordinary or Magic equipment.";
					}
					return null;
				default:
					return "Unknown currency.";
				}
			}
		}

		public CraftResult Prepare(JObject? original, bool corrupted, Currency currency, string guardEffect = "ModifyArmor", int? vaalOutcome = null)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Expected O, but got Unknown
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Expected O, but got Unknown
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			string text = Validate(original, corrupted, currency, guardEffect);
			if (text != null)
			{
				throw new InvalidOperationException(text);
			}
			JObject val = (JObject)((original == null) ? ((object)NewMagic()) : ((object)(JObject)((JToken)original).DeepClone()));
			JArray val2 = (JArray)val["Effects"];
			CraftResult craftResult = new CraftResult
			{
				Magic = val,
				Outcome = currency.ToString() + " applied."
			};
			switch (currency)
			{
			case Currency.Transmutation:
				AddEffect(val);
				break;
			case Currency.GemcuttersPrism:
				val["SocketCount"] = JToken.op_Implicit(((int?)val["SocketCount"]).GetValueOrDefault() + 1);
				craftResult.Outcome = "Added one shard slot (" + ((object)val["SocketCount"])?.ToString() + "/3).";
				break;
			case Currency.Augmentation:
				AddEffect(val);
				break;
			case Currency.Exalted:
			case Currency.PerfectExalted:
			{
				int num3 = (int)val["Rarity"];
				int ceiling = ((currency == Currency.PerfectExalted) ? 5 : ((num3 != 0) ? 3 : 0));
				int num4 = ExaltedRarity(num3, ((JContainer)val2).Count, ceiling);
				if (num4 < 0)
				{
					throw new InvalidOperationException("No higher rarity has room for another effect.");
				}
				val["Rarity"] = JToken.op_Implicit(num4);
				AddEffect(val);
				break;
			}
			case Currency.Regal:
				val["Rarity"] = JToken.op_Implicit(1);
				AddEffect(val);
				break;
			case Currency.Battle:
			case Currency.Guard:
			case Currency.Vitality:
			case Currency.Vigor:
			case Currency.Sorcery:
				val["Rarity"] = JToken.op_Implicit(1);
				AddEffect(val, EssenceEffect(currency, guardEffect));
				break;
			case Currency.Chaos:
			{
				List<int> list2 = MutableIndices(val);
				int num2 = list2[Next(list2.Count)];
				JObject val4 = (JObject)((JToken)val).DeepClone();
				((JArray)val4["Effects"]).RemoveAt(num2);
				val2[num2] = (JToken)(object)RollEffect(val4);
				break;
			}
			case Currency.Divine:
				RerollValues(val);
				break;
			case Currency.Annulment:
			{
				List<int> list = MutableIndices(val);
				RemoveEffect(val, list[Next(list.Count)]);
				break;
			}
			case Currency.Alchemy:
			{
				if (HasHistory(val))
				{
					throw new InvalidOperationException("Alchemy cannot erase an item's augment or temper history. Use a fresh base.");
				}
				val["Rarity"] = JToken.op_Implicit(1);
				val2.Clear();
				for (int j = 0; j < 4; j++)
				{
					AddEffect(val);
				}
				break;
			}
			case Currency.Vaal:
				switch (vaalOutcome ?? Next(4))
				{
				case 0:
					craftResult.Outcome = "Corrupted: existing effects unchanged.";
					break;
				case 1:
					if (CanAddEffect(val))
					{
						AddEffect(val);
						craftResult.Outcome = "Corrupted: gained one additional effect.";
					}
					else
					{
						craftResult.Outcome = "Corrupted: no eligible additional effect remained; existing effects unchanged.";
					}
					break;
				case 2:
					RerollValues(val);
					craftResult.Outcome = "Corrupted: numerical rolls rerolled.";
					break;
				case 3:
				{
					int num = 0;
					for (int i = 0; i < ((JContainer)val2).Count; i++)
					{
						EffectDefinition effectDefinition = definition((string)val2[i][(object)"EffectType"], (int)val["Rarity"]);
						if (effectDefinition != null && effectDefinition.Mutable)
						{
							JObject val3 = (JObject)((JToken)val).DeepClone();
							((JArray)val3["Effects"]).RemoveAt(i);
							if (CanAddEffect(val3))
							{
								val2[i] = (JToken)(object)RollEffect(val3);
								num++;
							}
						}
					}
					craftResult.Outcome = ((num > 0) ? "Corrupted: eligible effects replaced." : "Corrupted: no eligible replacement effects; existing effects unchanged.");
					break;
				}
				default:
					throw new InvalidOperationException("Invalid Vaal outcome.");
				}
				craftResult.Corrupted = true;
				craftResult.ApplyMagic = original != null || ((JContainer)val2).Count > 0;
				break;
			}
			return craftResult;
		}

		private static JObject NewMagic()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			return new JObject
			{
				["Version"] = JToken.op_Implicit(3),
				["Rarity"] = JToken.op_Implicit(0),
				["Effects"] = (JToken)new JArray(),
				["AugmentedEffectIndex"] = JToken.op_Implicit(-1),
				["AugmentedEffectIndices"] = (JToken)new JArray(),
				["TemperedEffectIndices"] = (JToken)new JArray(),
				["SocketCount"] = JToken.op_Implicit(0),
				["Sockets"] = (JToken)new JArray(),
				["IsUnidentified"] = JToken.op_Implicit(false)
			};
		}

		public static string EssenceEffect(Currency currency, string guardEffect)
		{
			return currency switch
			{
				Currency.Battle => "ModifyPhysicalDamage", 
				Currency.Guard => guardEffect, 
				Currency.Vitality => "IncreaseHealth", 
				Currency.Vigor => "IncreaseStamina", 
				Currency.Sorcery => "IncreaseEitr", 
				_ => throw new ArgumentException("Not an essence."), 
			};
		}

		private void AddEffect(JObject magic, string? guaranteed = null)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			((JArray)magic["Effects"]).Add((JToken)(object)RollEffect(magic, guaranteed));
		}

		private bool CanAddEffect(JObject magic)
		{
			return available(magic).Any((EffectDefinition e) => e.Mutable && e.Weight > 0.0 && IsFinite(e.Weight));
		}

		private JObject RollEffect(JObject magic, string? guaranteed = null)
		{
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			List<EffectDefinition> list = (from e in available(magic)
				where e.Weight > 0.0 && IsFinite(e.Weight) && e.Mutable
				select e).ToList();
			EffectDefinition effectDefinition;
			if (guaranteed != null)
			{
				effectDefinition = list.FirstOrDefault((EffectDefinition e) => e.Type == guaranteed) ?? throw new InvalidOperationException("The guaranteed effect is not eligible for this item, or already exists.");
			}
			else
			{
				double num = list.Sum((EffectDefinition e) => e.Weight);
				if (!(num > 0.0) || !IsFinite(num))
				{
					throw new InvalidOperationException("No eligible effects remain.");
				}
				double num2 = Sample() * num;
				effectDefinition = list[list.Count - 1];
				foreach (EffectDefinition item in list)
				{
					num2 -= item.Weight;
					if (num2 < 0.0)
					{
						effectDefinition = item;
						break;
					}
				}
			}
			return new JObject
			{
				["Version"] = JToken.op_Implicit(1),
				["EffectType"] = JToken.op_Implicit(effectDefinition.Type),
				["EffectValue"] = JToken.op_Implicit(RollValue(effectDefinition))
			};
		}

		private static bool IsFinite(double value)
		{
			if (!double.IsNaN(value))
			{
				return !double.IsInfinity(value);
			}
			return false;
		}

		public static int MaximumEffectCount(IEnumerable<KeyValuePair<int, float>> counts)
		{
			return (from e in counts
				where e.Key >= 0 && e.Key <= 12 && e.Value > 0f && IsFinite(e.Value)
				select e.Key).DefaultIfEmpty(0).Max();
		}

		private double RollValue(EffectDefinition effect)
		{
			if (!effect.Min.HasValue && !effect.Max.HasValue)
			{
				return 1.0;
			}
			if (!effect.Min.HasValue || !effect.Max.HasValue || !IsFinite(effect.Min.Value) || !IsFinite(effect.Max.Value) || !IsFinite(effect.Increment) || effect.Max < effect.Min || effect.Increment < 0.0)
			{
				throw new InvalidOperationException("Invalid roll range for " + effect.Type + ".");
			}
			if (effect.Increment == 0.0)
			{
				return effect.Min.Value;
			}
			double num = Math.Floor((effect.Max.Value - effect.Min.Value) / effect.Increment + 1E-06);
			if (num > 2147483646.0)
			{
				throw new InvalidOperationException("Roll range is too large.");
			}
			return effect.Min.Value + (double)Next((int)num + 1) * effect.Increment;
		}

		private List<int> MutableIndices(JObject magic)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			JArray effects = (JArray)magic["Effects"];
			return (from i in Enumerable.Range(0, ((JContainer)effects).Count)
				where definition((string)effects[i][(object)"EffectType"], (int)magic["Rarity"])?.Mutable ?? false
				select i).ToList();
		}

		private List<Tuple<JObject, EffectDefinition>> DivineTargets(JObject magic)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			List<Tuple<JObject, EffectDefinition>> list = new List<Tuple<JObject, EffectDefinition>>();
			JToken obj = magic["TemperedEffectIndices"];
			JToken obj2 = ((obj is JArray) ? obj : null);
			List<int> list2 = ((obj2 != null) ? ((JContainer)obj2).Values<int>().ToList() : null) ?? new List<int>();
			JArray val = (JArray)magic["Effects"];
			for (int i = 0; i < ((JContainer)val).Count; i++)
			{
				JObject val2 = (JObject)val[i];
				EffectDefinition effectDefinition = definition((string)val2["EffectType"], (int)magic["Rarity"]);
				if (!list2.Contains(i) && effectDefinition != null && effectDefinition.Mutable && effectDefinition.Min.HasValue && effectDefinition.Max > effectDefinition.Min && effectDefinition.Increment > 0.0)
				{
					list.Add(Tuple.Create<JObject, EffectDefinition>(val2, effectDefinition));
				}
			}
			return list;
		}

		private void RerollValues(JObject magic)
		{
			foreach (Tuple<JObject, EffectDefinition> item in DivineTargets(magic))
			{
				item.Item1["EffectValue"] = JToken.op_Implicit(RollValue(item.Item2));
			}
		}

		private int ExaltedRarity(int rarity, int effectCount, int ceiling)
		{
			for (int i = rarity; i <= ceiling; i++)
			{
				int num = maximumEffects(i);
				if (num < 0 || num > 12)
				{
					throw new InvalidOperationException("Invalid Epic Loot effect limit.");
				}
				if (effectCount < num)
				{
					return i;
				}
			}
			return -1;
		}

		public static bool HasHistory(JObject magic)
		{
			if ((((int?)magic["AugmentedEffectIndex"]) ?? (-1)) < 0)
			{
				JToken obj = magic["AugmentedEffectIndices"];
				JToken obj2 = ((obj is JArray) ? obj : null);
				if (obj2 == null || ((JContainer)obj2).Count <= 0)
				{
					JToken obj3 = magic["TemperedEffectIndices"];
					JToken obj4 = ((obj3 is JArray) ? obj3 : null);
					if (obj4 == null)
					{
						return false;
					}
					return ((JContainer)obj4).Count > 0;
				}
			}
			return true;
		}

		private static void RemoveEffect(JObject magic, int index)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			((JArray)magic["Effects"]).RemoveAt(index);
			int num = ((int?)magic["AugmentedEffectIndex"]) ?? (-1);
			magic["AugmentedEffectIndex"] = JToken.op_Implicit((num == index) ? (-1) : ((num > index) ? (num - 1) : num));
			string[] array = new string[2] { "AugmentedEffectIndices", "TemperedEffectIndices" };
			foreach (string text in array)
			{
				JToken obj = magic[text];
				JArray val = (JArray)(object)((obj is JArray) ? obj : null);
				if (val != null)
				{
					magic[text] = (JToken)new JArray((object)(from num2 in ((JContainer)val).Values<int>()
						where num2 != index
						select (num2 <= index) ? num2 : (num2 - 1)));
				}
			}
		}

		private double Sample()
		{
			double num = random();
			if (!IsFinite(num) || num < 0.0 || num >= 1.0)
			{
				throw new InvalidOperationException("Random source must return a value in [0, 1).");
			}
			return num;
		}

		private int Next(int count)
		{
			if (count <= 0)
			{
				throw new InvalidOperationException("Empty random choice.");
			}
			return (int)(Sample() * (double)count);
		}
	}
	public static class CurrencyDropRules
	{
		private static readonly string[] Qualities = new string[6] { "Magic", "Rare", "Epic", "Legendary", "Mythic", "Ancient" };

		private static readonly string[] Materials = new string[6] { "Dust", "Essence", "Reagent", "Shard", "Runestone", "EtchedRunestone" };

		public static string QualityName(int quality)
		{
			return Qualities[quality];
		}

		public static int MinimumQuality(Currency currency)
		{
			switch (currency)
			{
			default:
				return (currency == Currency.Vaal) ? 1 : 0;
			case Currency.Exalted:
			case Currency.GemcuttersPrism:
				return 3;
			case Currency.Divine:
			case Currency.PerfectExalted:
				return 4;
			}
		}

		public static string MinimumQualityName(Currency currency)
		{
			return Qualities[MinimumQuality(currency)];
		}

		public static int VisualQuality(Currency currency)
		{
			if (currency > Currency.Augmentation)
			{
				switch (currency)
				{
				default:
					return 1;
				case Currency.Vaal:
					return 2;
				case Currency.Divine:
				case Currency.PerfectExalted:
					return 3;
				}
			}
			return 0;
		}

		public static float DefaultChance(Currency currency)
		{
			return (currency <= Currency.Augmentation) ? 50 : 5;
		}

		public static bool Eligible(Currency currency, int lootQuality)
		{
			if (lootQuality >= MinimumQuality(currency))
			{
				return lootQuality < Qualities.Length;
			}
			return false;
		}

		public static int MaterialQuality(string prefab)
		{
			int i;
			for (i = 0; i < Qualities.Length; i++)
			{
				if (Materials.Any((string m) => prefab == m + Qualities[i]))
				{
					return i;
				}
			}
			return -1;
		}

		public static bool ShouldDrop(float chancePercent, double sample)
		{
			if (float.IsNaN(chancePercent) || float.IsInfinity(chancePercent) || chancePercent < 0f || chancePercent > 100f)
			{
				throw new InvalidOperationException("Drop chance must be between 0 and 100.");
			}
			if (double.IsNaN(sample) || sample < 0.0 || sample >= 1.0)
			{
				throw new InvalidOperationException("Drop sample must be in [0, 1).");
			}
			return sample * 100.0 < (double)chancePercent;
		}
	}
	public static class CurrencyMaterials
	{
		public static string Dust(Currency currency)
		{
			return "Dust" + CurrencyDropRules.MinimumQualityName(currency);
		}

		public static string Essence(Currency currency)
		{
			return "Essence" + CurrencyDropRules.MinimumQualityName(currency);
		}

		public static JObject SacrificeDefinition(Currency currency, string itemName, string marker)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			JObject val = new JObject();
			val["IsMagic"] = JToken.op_Implicit(false);
			val["IsUnidentified"] = JToken.op_Implicit(false);
			val["ItemNames"] = (JToken)new JArray((object)itemName);
			val["AmmoTypeSuffixes"] = (JToken)new JArray((object)marker);
			val["Products"] = (JToken)new JArray(new object[2]
			{
				(object)new JObject
				{
					["Item"] = JToken.op_Implicit(Dust(currency)),
					["Amount"] = JToken.op_Implicit(1)
				},
				(object)new JObject
				{
					["Item"] = JToken.op_Implicit(Essence(currency)),
					["Amount"] = JToken.op_Implicit(1)
				}
			});
			return val;
		}
	}
}