Decompiled source of ItemUpgrader v0.5.1

BepInEx/plugins/ItemUpgrader/ItemUpgrader.dll

Decompiled 34 minutes ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Item Upgrader")]
[assembly: AssemblyDescription("Local item exchange roulette for Valheim")]
[assembly: AssemblyFileVersion("0.5.1.0")]
[assembly: AssemblyVersion("0.5.1.0")]
namespace ValheimItemUpgrader;

public static class GridWindow
{
	public static int PoolSize(double viewport, double rowStride, int columns)
	{
		return ((int)Math.Ceiling(viewport / rowStride) + 2) * columns;
	}

	public static int FirstIndex(double offset, double rowStride, int columns, int count)
	{
		int val = Math.Max(0, (int)Math.Floor(Math.Max(0.0, offset - 8.0) / rowStride) - 1);
		int val2 = Math.Max(0, (count + columns - 1) / columns - 1);
		return Math.Min(val, val2) * columns;
	}

	public static double ContentHeight(int count, int columns, double cellHeight, double gap)
	{
		if (count != 0)
		{
			return 16.0 + Math.Ceiling((double)count / (double)columns) * (cellHeight + gap) - gap;
		}
		return 16.0;
	}
}
public sealed class RewardReceipt
{
	public string Prefab;

	public int Amount = 1;

	public int Quality = 1;

	public string Transaction;
}
[BepInPlugin("valheim.itemupgrader", "Item Upgrader", "0.5.1")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Guid = "valheim.itemupgrader";

	public const string Version = "0.5.1";

	private const string ReceiptKey = "valheim.itemupgrader.pendingReward.v1";

	public static Plugin Instance;

	private static int closedFrame = -1;

	private ConfigEntry<KeyboardShortcut> hotkey;

	private ConfigEntry<bool> modEnabled;

	private ConfigEntry<double> returnRate;

	private ConfigEntry<double> maxChance;

	private ConfigEntry<double> craftingMarkup;

	private ConfigEntry<double> equipmentValueFactor;

	private ConfigEntry<double> upgradeChanceExponent;

	private ConfigEntry<float> spinSeconds;

	private ConfigEntry<float> scrollRows;

	private ConfigEntry<int> maximumRewardAmount;

	private Harmony harmony;

	private UpgraderUI ui;

	private Player player;

	private float refreshTime;

	private bool initialized;

	private bool invalidReceipt;

	private bool progressDirty = true;

	private CatalogProgress progress = new CatalogProgress();

	private TextKey? catalogError;

	private TextKey statusKey = TextKey.Choose;

	private object[] statusArgs = new object[0];

	private RewardReceipt pending;

	private float spinStart;

	private float spinDuration;

	private double spinAngle;

	private double spinEndAngle;

	private double spinChance;

	private bool spinWin;

	private string spinTarget;

	private int spinTargetQuantity;

	public static bool IsOpen
	{
		get
		{
			if ((Object)(object)Instance != (Object)null && Instance.ui != null)
			{
				return Instance.ui.Visible;
			}
			return false;
		}
	}

	public static bool BlocksInput
	{
		get
		{
			if (!IsOpen)
			{
				return Time.frameCount == closedFrame;
			}
			return true;
		}
	}

	public ValueCatalog Catalog { get; private set; }

	public ItemData Source { get; private set; }

	public CatalogItem Target { get; private set; }

	public int Quantity { get; private set; }

	public int TargetQuantity { get; private set; }

	public int RewardRemaining
	{
		get
		{
			if (pending != null)
			{
				return pending.Amount;
			}
			return 0;
		}
	}

	public int MaximumRewardAmount => maximumRewardAmount.Value;

	public bool Spinning { get; private set; }

	public string Status
	{
		get
		{
			if (statusKey == TextKey.Success)
			{
				string text = ((Localization.instance == null) ? spinTarget : Localization.instance.Localize(spinTarget));
				return ModText.Format(TextKey.Success, text, spinTargetQuantity);
			}
			return ModText.Format(statusKey, statusArgs);
		}
	}

	public bool HasReward => pending != null;

	public CatalogItem RewardItem
	{
		get
		{
			if (pending != null && Catalog != null)
			{
				return Catalog.FindReward(pending.Prefab);
			}
			return null;
		}
	}

	public bool ShowAllItems => progress.ShowAll;

	public int ProgressRevision => progress.Revision;

	public int UnlockedItemCount => progress.UnlockedCount;

	public Player LocalPlayer => player;

	public string HotkeyLabel => ((object)hotkey.Value/*cast due to .constrained prefix*/).ToString();

	public float ScrollRowsPerNotch => scrollRows.Value;

	public double Stake
	{
		get
		{
			if (Catalog != null)
			{
				return Catalog.StakeValue(Source, Quantity);
			}
			return 0.0;
		}
	}

	public double TargetTotal
	{
		get
		{
			if (Target != null)
			{
				return RollMath.TargetValue(Target.Value, TargetQuantity);
			}
			return 0.0;
		}
	}

	public double Chance => RollMath.Chance(Stake, TargetTotal, returnRate.Value, maxChance.Value, upgradeChanceExponent.Value);

	public double DisplayChance
	{
		get
		{
			if (!Spinning && (Source != null || !(spinAngle > 0.0)))
			{
				return Chance;
			}
			return spinChance;
		}
	}

	public bool CanChangeSelection
	{
		get
		{
			if (!Spinning && !HasReward)
			{
				return !invalidReceipt;
			}
			return false;
		}
	}

	public static void JustClosed()
	{
		closedFrame = Time.frameCount;
	}

	private void Awake()
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Expected O, but got Unknown
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Expected O, but got Unknown
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Expected O, but got Unknown
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Expected O, but got Unknown
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Expected O, but got Unknown
		//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Expected O, but got Unknown
		//IL_023b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Expected O, but got Unknown
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Expected O, but got Unknown
		//IL_0386: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Expected O, but got Unknown
		//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03db: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		ImportPreviousConfig();
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the local upgrader UI.");
		hotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "OpenKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Key for opening and closing the upgrader.");
		returnRate = ((BaseUnityPlugin)this).Config.Bind<double>("Balance", "ReturnRate", 0.85, new ConfigDescription("Base return. When target is more expensive: chance = ReturnRate * (stake / target)^UpgradeChanceExponent. No minimum chance.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(0.01, 1.0), Array.Empty<object>()));
		maxChance = ((BaseUnityPlugin)this).Config.Bind<double>("Balance", "MaximumChance", 0.95, new ConfigDescription("Maximum probability: 0.95 means 95%.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(0.01, 1.0), Array.Empty<object>()));
		craftingMarkup = ((BaseUnityPlugin)this).Config.Bind<double>("Balance", "CraftingMarkup", 1.05, new ConfigDescription("Labor multiplier, applied once to the raw acquisition chain. Custom ItemValues.json entries take precedence.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(1.0, 3.0), Array.Empty<object>()));
		equipmentValueFactor = ((BaseUnityPlugin)this).Config.Bind<double>("Balance", "EquipmentValueFactor", 0.6, new ConfigDescription("Exchange value as a share of raw equipment/cast acquisition cost, also limited by category and biome. Quality never exceeds x2.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(0.2, 1.0), Array.Empty<object>()));
		upgradeChanceExponent = ((BaseUnityPlugin)this).Config.Bind<double>("Balance", "UpgradeChanceExponent", 1.25, new ConfigDescription("Extra risk for targets worth more than the stake. 1 restores a linear curve; 1.25 discourages tiny stakes for huge resource quantities.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(1.0, 2.0), Array.Empty<object>()));
		spinSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "SpinSeconds", 5f, new ConfigDescription("Wheel animation duration in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
		scrollRows = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "ScrollRowsPerNotch", 2f, new ConfigDescription("Inventory/catalog rows scrolled per mouse wheel notch.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 6f), Array.Empty<object>()));
		maximumRewardAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Balance", "MaximumRewardAmount", 1000, new ConfigDescription("Maximum selected reward quantity. Larger rewards can be claimed in several batches.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10000), Array.Empty<object>()));
		ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("Internal", "AnimationVersion", "", "Tracks the one-time migration to the five-second animation.");
		if (val.Value != "0.2.0")
		{
			spinSeconds.Value = 5f;
			val.Value = "0.2.0";
		}
		ConfigEntry<string> val2 = ((BaseUnityPlugin)this).Config.Bind<string>("Internal", "EconomyVersion", "", "Tracks one-time changes to former economy defaults.");
		if (val2.Value != "0.4.0")
		{
			if (Math.Abs(returnRate.Value - 0.9) < 1E-09)
			{
				returnRate.Value = 0.85;
			}
			if (Math.Abs(craftingMarkup.Value - 1.15) < 1E-09)
			{
				craftingMarkup.Value = 1.05;
			}
			val2.Value = "0.4.0";
		}
		harmony = new Harmony("valheim.itemupgrader");
		harmony.PatchAll(typeof(Plugin).Assembly);
		RecordStatus(TextKey.Choose);
		Quantity = 1;
		TargetQuantity = 1;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Item Upgrader 0.5.1 loaded. Local only. Open with " + ((object)hotkey.Value/*cast due to .constrained prefix*/).ToString() + "."));
	}

	private void ImportPreviousConfig()
	{
		if (File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath))
		{
			return;
		}
		try
		{
			string[] array = (from p in Directory.GetFiles(Paths.ConfigPath, "*.cfg")
				where Path.GetFileName(p).EndsWith(".valheim.itemupgrader.cfg", StringComparison.OrdinalIgnoreCase)
				select p).ToArray();
			if (array.Length == 1)
			{
				File.Copy(array[0], ((BaseUnityPlugin)this).Config.ConfigFilePath, overwrite: false);
				((BaseUnityPlugin)this).Config.Reload();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Imported settings from the previous plugin ID.");
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not import previous settings: " + ex.Message));
		}
	}

	private void Update()
	{
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer != (Object)(object)player)
		{
			if (ui != null)
			{
				ui.Destroy();
			}
			ui = null;
			player = localPlayer;
			Source = null;
			Target = null;
			Quantity = 1;
			TargetQuantity = 1;
			Spinning = false;
			pending = null;
			invalidReceipt = false;
			spinAngle = 0.0;
			initialized = false;
			Catalog = null;
			catalogError = null;
			progress = new CatalogProgress();
			progressDirty = true;
		}
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		if (!modEnabled.Value)
		{
			if (ui != null && ui.Visible)
			{
				ui.Hide();
			}
			return;
		}
		if (!initialized && (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count > 0 && ObjectDB.instance.m_recipes.Count > 0 && (Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.m_prefabs.Count > 0 && !((Character)player).InCutscene())
		{
			Initialize();
		}
		if (!initialized)
		{
			return;
		}
		if (Spinning)
		{
			float num = Mathf.Clamp01((Time.unscaledTime - spinStart) / spinDuration);
			if (ui != null)
			{
				ui.SetAngle((float)(spinAngle * RollMath.SmoothSpin(num)));
			}
			if (num >= 1f)
			{
				if (ui != null)
				{
					ui.SetAngle((float)spinEndAngle);
				}
				CompleteSpin();
			}
		}
		if (ui != null && ui.Visible && ((Character)player).IsDead())
		{
			ui.Hide();
		}
		KeyboardShortcut value = hotkey.Value;
		if (((KeyboardShortcut)(ref value)).IsDown())
		{
			if (ui != null && ui.Visible)
			{
				ui.Hide();
			}
			else if (!((Character)player).IsDead() && !((Character)player).InCutscene() && !InventoryGui.IsVisible() && !Menu.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()))
			{
				Open();
			}
		}
		if (ui == null || !ui.Visible)
		{
			return;
		}
		if (Input.GetKeyDown((KeyCode)27))
		{
			ui.Hide();
			return;
		}
		Cursor.lockState = (CursorLockMode)0;
		Cursor.visible = true;
		if (Time.unscaledTime > refreshTime)
		{
			refreshTime = Time.unscaledTime + 0.35f;
			RefreshProgress();
			ValidateSource();
			ui.Refresh(force: false);
		}
	}

	private void Initialize()
	{
		SyncLanguage();
		try
		{
			Catalog = new ValueCatalog(Path.Combine(Paths.ConfigPath, "ItemUpgrader"), craftingMarkup.Value, equipmentValueFactor.Value, ((BaseUnityPlugin)this).Logger);
			Catalog.Build();
			progressDirty = true;
			RefreshProgress();
			LoadReceipt();
			initialized = true;
			RecordStatus(invalidReceipt ? TextKey.InvalidReceipt : ((pending == null) ? TextKey.Choose : TextKey.PendingReward));
			((MonoBehaviour)this).StartCoroutine(PrewarmUi(player));
		}
		catch (Exception ex)
		{
			initialized = true;
			Catalog = null;
			catalogError = TextKey.CatalogError;
			((BaseUnityPlugin)this).Logger.LogError((object)("ItemUpgrader initialization failed: " + ex));
		}
	}

	private IEnumerator PrewarmUi(Player owner)
	{
		yield return null;
		if ((Object)(object)player != (Object)(object)owner || Catalog == null)
		{
			yield break;
		}
		try
		{
			if (ui == null)
			{
				ui = new UpgraderUI(this);
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("UI prewarm failed: " + ex));
			yield break;
		}
		UpgraderUI prepared = ui;
		IEnumerator steps = prepared.Prewarm();
		while ((Object)(object)player == (Object)(object)owner && ui == prepared && steps.MoveNext())
		{
			yield return steps.Current;
		}
	}

	private void Open()
	{
		SyncLanguage();
		if (Catalog == null)
		{
			((Character)player).Message((MessageType)2, ModText.Get(catalogError ?? TextKey.CatalogNotReady), 0, (Sprite)null, false);
			return;
		}
		try
		{
			if (ui == null)
			{
				ui = new UpgraderUI(this);
			}
			RefreshProgress();
			ValidateSource();
			ui.Show();
		}
		catch (Exception ex)
		{
			if (ui != null)
			{
				ui.Destroy();
			}
			ui = null;
			((BaseUnityPlugin)this).Logger.LogError((object)("Could not create upgrader UI: " + ex));
			((Character)player).Message((MessageType)2, ModText.Get(TextKey.OpenError), 0, (Sprite)null, false);
		}
	}

	public void MarkProgressDirty(Player owner)
	{
		if ((Object)(object)owner == (Object)(object)player)
		{
			progressDirty = true;
		}
	}

	public void RefreshProgress()
	{
		if (progressDirty && Catalog != null && !((Object)(object)player == (Object)null))
		{
			progress.Refresh((IEnumerable<CatalogItem>)Catalog.Items, (Func<string, bool>)player.IsMaterialKnown, (Func<string, bool>)player.IsRecipeKnown);
			progressDirty = false;
			if (!Spinning && Target != null && !progress.CanSelect(Target))
			{
				Target = null;
				TargetQuantity = 1;
			}
		}
	}

	public bool CanChooseTarget(CatalogItem item)
	{
		return progress.CanSelect(item);
	}

	public void SetShowAllItems(bool enabled)
	{
		if (Spinning || invalidReceipt)
		{
			return;
		}
		RefreshProgress();
		progress.SetShowAll(enabled);
		if (!progress.CanSelect(Target))
		{
			Target = null;
			TargetQuantity = 1;
		}
		if (!HasReward)
		{
			spinAngle = 0.0;
			if (ui != null)
			{
				ui.ResetWheel();
			}
			RecordStatus(enabled ? TextKey.AllItemsEnabled : TextKey.ProgressEnabled);
		}
		if (ui != null)
		{
			ui.Refresh(force: true);
		}
	}

	public void SelectSource(ItemData item)
	{
		if (CanChangeSelection && item != null && ((Humanoid)player).GetInventory().ContainsItem(item))
		{
			if (item.m_equipped)
			{
				SetStatus(TextKey.Unequip);
				return;
			}
			if (Catalog.Find(item) == null)
			{
				SetStatus(TextKey.ExchangeDisabled);
				return;
			}
			Source = item;
			Quantity = 1;
			spinAngle = 0.0;
			ui.ResetWheel();
			RecordStatus(TextKey.SourceSelected);
			ui.Refresh(force: true);
		}
	}

	public void SelectTarget(CatalogItem target)
	{
		RefreshProgress();
		if (CanChangeSelection && CanChooseTarget(target))
		{
			Target = target;
			TargetQuantity = 1;
			spinAngle = 0.0;
			RecordStatus(TextKey.StakeWarning);
			ui.ResetWheel();
			ui.Refresh(force: true);
		}
	}

	public void SetQuantity(int quantity)
	{
		if (CanChangeSelection && Source != null)
		{
			Quantity = Math.Max(1, Math.Min(Source.m_stack, quantity));
			ui.Refresh(force: false);
		}
	}

	public void SetTargetQuantity(int quantity)
	{
		if (CanChangeSelection && Target != null)
		{
			TargetQuantity = Math.Max(1, Math.Min(MaximumRewardAmount, quantity));
			spinAngle = 0.0;
			if (ui != null)
			{
				ui.ResetWheel();
				ui.Refresh(force: false);
			}
		}
	}

	public void ClearSource()
	{
		if (CanChangeSelection)
		{
			Source = null;
			Quantity = 1;
			spinAngle = 0.0;
			ui.ResetWheel();
			ui.Refresh(force: true);
		}
	}

	private void ValidateSource()
	{
		if (Source != null)
		{
			if ((Object)(object)player == (Object)null || !((Humanoid)player).GetInventory().ContainsItem(Source) || Source.m_equipped || Source.m_stack < 1 || Catalog.Find(Source) == null)
			{
				Source = null;
				Quantity = 1;
			}
			else
			{
				Quantity = Math.Min(Quantity, Source.m_stack);
			}
		}
	}

	public bool CanRoll()
	{
		RefreshProgress();
		ValidateSource();
		if (modEnabled.Value && (Object)(object)player != (Object)null && !((Character)player).IsDead() && CanChangeSelection && Source != null && CanChooseTarget(Target) && Quantity >= 1)
		{
			return Chance > 0.0;
		}
		return false;
	}

	public void Roll()
	{
		if (!CanRoll())
		{
			return;
		}
		Inventory inventory = ((Humanoid)player).GetInventory();
		if (!inventory.ContainsItem(Source) || Source.m_stack < Quantity || Source.m_equipped)
		{
			SetStatus(TextKey.SourceChanged);
			return;
		}
		if ((Object)(object)ObjectDB.instance.GetItemPrefab(Target.Id) == (Object)null)
		{
			SetStatus(TextKey.TargetUnavailable);
			return;
		}
		double sample = UniformSample();
		double chance = Chance;
		bool flag = RollMath.Wins(sample, chance);
		string text = System.Guid.NewGuid().ToString("N");
		RewardReceipt rewardReceipt = (flag ? new RewardReceipt
		{
			Prefab = Target.Id,
			Amount = TargetQuantity,
			Quality = 1,
			Transaction = text
		} : null);
		string value = (flag ? JsonConvert.SerializeObject((object)rewardReceipt) : null);
		string name = ((Object)Source.m_dropPrefab).name;
		int quantity = Quantity;
		double stake = Stake;
		if (!inventory.RemoveItem(Source, quantity))
		{
			SetStatus(TextKey.RemoveFailed);
			return;
		}
		pending = rewardReceipt;
		if (flag)
		{
			player.m_customData["valheim.itemupgrader.pendingReward.v1"] = value;
		}
		else
		{
			player.m_customData.Remove("valheim.itemupgrader.pendingReward.v1");
		}
		spinChance = chance;
		spinWin = flag;
		spinTarget = Target.Template.m_shared.m_name;
		spinTargetQuantity = TargetQuantity;
		spinEndAngle = RollMath.EndAngle(sample);
		spinAngle = 2160.0 + spinEndAngle;
		spinStart = Time.unscaledTime;
		spinDuration = spinSeconds.Value;
		Spinning = true;
		Source = null;
		Quantity = 1;
		RecordStatus(TextKey.Spinning);
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Upgrade " + text + ": " + name + " x" + quantity + " (" + stake.ToString("0.####", CultureInfo.InvariantCulture) + ") -> " + Target.Id + " x" + TargetQuantity + "; chance=" + RollMath.Percent(chance) + "; success=" + flag));
		if (ui != null)
		{
			ui.SetAngle(0f);
			ui.Refresh(force: true);
		}
	}

	private void CompleteSpin()
	{
		Spinning = false;
		RecordStatus(spinWin ? TextKey.Success : TextKey.Failure);
		if (ui != null)
		{
			ui.ShowResult(spinWin);
			ui.Refresh(force: true);
		}
	}

	public void Claim()
	{
		if (Spinning || pending == null || (Object)(object)player == (Object)null || ((Character)player).IsDead())
		{
			return;
		}
		if (pending.Amount < 1 || pending.Amount > 100000 || pending.Quality != 1)
		{
			SetStatus(TextKey.BadReward);
			return;
		}
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(pending.Prefab);
		ItemDrop val = (((Object)(object)itemPrefab == (Object)null) ? null : itemPrefab.GetComponent<ItemDrop>());
		if ((Object)(object)val == (Object)null)
		{
			SetStatus(TextKey.MissingReward);
			return;
		}
		Inventory inventory = ((Humanoid)player).GetInventory();
		int num = 0;
		while (pending.Amount > 0)
		{
			ItemData val2 = val.m_itemData.Clone();
			val2.m_dropPrefab = itemPrefab;
			val2.m_quality = 1;
			val2.m_equipped = false;
			val2.m_durability = val2.GetMaxDurability();
			int num2 = Math.Max(1, val2.m_shared.m_maxStackSize);
			long num3 = (long)Math.Max(0, inventory.GetWidth() * inventory.GetHeight() - inventory.GetAllItems().Count) * (long)num2;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem.m_shared.m_name == val2.m_shared.m_name && allItem.m_quality == 1 && allItem.m_worldLevel == val2.m_worldLevel)
				{
					num3 += Math.Max(0, num2 - allItem.m_stack);
				}
			}
			int num4 = (int)Math.Min(pending.Amount, Math.Min(num2, num3));
			if (num4 < 1 || !inventory.CanAddItem(val2, num4))
			{
				break;
			}
			val2.m_stack = num4;
			bool num5 = inventory.AddItem(val2);
			int num6 = (num5 ? num4 : Math.Max(0, num4 - val2.m_stack));
			pending.Amount -= num6;
			num += num6;
			if (!num5)
			{
				break;
			}
		}
		if (pending.Amount == 0)
		{
			player.m_customData.Remove("valheim.itemupgrader.pendingReward.v1");
			pending = null;
		}
		else
		{
			player.m_customData["valheim.itemupgrader.pendingReward.v1"] = JsonConvert.SerializeObject((object)pending);
		}
		if (num == 0)
		{
			RecordStatus(TextKey.NoSpace);
		}
		else if (pending == null)
		{
			RecordStatus(TextKey.Claimed, num);
		}
		else
		{
			RecordStatus(TextKey.PartiallyClaimed, num, pending.Amount);
		}
		if (ui != null)
		{
			ui.Refresh(force: true);
		}
	}

	public void ReloadValues()
	{
		if (Spinning)
		{
			return;
		}
		try
		{
			string id = ((Target == null) ? null : Target.Id);
			ValueCatalog valueCatalog = new ValueCatalog(Path.Combine(Paths.ConfigPath, "ItemUpgrader"), craftingMarkup.Value, equipmentValueFactor.Value, ((BaseUnityPlugin)this).Logger);
			valueCatalog.Build();
			Catalog = valueCatalog;
			Target = Catalog.Find(id);
			progressDirty = true;
			RefreshProgress();
			ValidateSource();
			if (ui != null)
			{
				ui.RefreshCatalog();
			}
			SetStatus(TextKey.PricesReloaded);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Price reload failed: " + ex));
			SetStatus(TextKey.PriceReloadError);
		}
	}

	private void LoadReceipt()
	{
		string text = "valheim.itemupgrader.pendingReward.v1";
		if (!player.m_customData.TryGetValue("valheim.itemupgrader.pendingReward.v1", out var value))
		{
			string[] array = player.m_customData.Keys.Where((string k) => k.EndsWith(".valheim.itemupgrader.pendingReward.v1", StringComparison.Ordinal)).ToArray();
			if (array.Length == 0)
			{
				return;
			}
			if (array.Length != 1)
			{
				invalidReceipt = true;
				((BaseUnityPlugin)this).Logger.LogError((object)"Several legacy rewards found; migration blocked to avoid losing rewards.");
				return;
			}
			text = array[0];
			value = player.m_customData[text];
		}
		try
		{
			RewardReceipt rewardReceipt = JsonConvert.DeserializeObject<RewardReceipt>(value);
			if (rewardReceipt == null || string.IsNullOrEmpty(rewardReceipt.Prefab) || rewardReceipt.Amount < 1 || rewardReceipt.Amount > 100000 || rewardReceipt.Quality != 1)
			{
				throw new InvalidDataException("Invalid reward receipt");
			}
			pending = rewardReceipt;
			if (text != "valheim.itemupgrader.pendingReward.v1")
			{
				player.m_customData["valheim.itemupgrader.pendingReward.v1"] = value;
				player.m_customData.Remove(text);
			}
		}
		catch (Exception ex)
		{
			invalidReceipt = true;
			((BaseUnityPlugin)this).Logger.LogError((object)("Pending reward data is invalid; further rolls blocked: " + ex));
		}
	}

	private static double UniformSample()
	{
		byte[] array = new byte[8];
		using (RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create())
		{
			randomNumberGenerator.GetBytes(array);
		}
		return (double)(BitConverter.ToUInt64(array, 0) >> 11) * 1.1102230246251565E-16;
	}

	private void RecordStatus(TextKey key, params object[] args)
	{
		statusKey = key;
		statusArgs = args;
	}

	public void SetStatus(TextKey key, params object[] args)
	{
		RecordStatus(key, args);
		if (ui != null)
		{
			ui.Refresh(force: false);
		}
	}

	public void SyncLanguage()
	{
		if (Localization.instance != null)
		{
			ModText.SetLanguage(Localization.instance.GetSelectedLanguage());
		}
	}

	private void OnDestroy()
	{
		if (ui != null)
		{
			ui.Destroy();
		}
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}
}
[HarmonyPatch(typeof(Player), "AddKnownItem")]
internal static class KnownMaterialPatch
{
	private static void Prefix(Player __instance, ItemData __0, out bool __state)
	{
		__state = __0 != null && __0.m_shared != null && !__instance.IsMaterialKnown(__0.m_shared.m_name);
	}

	private static void Postfix(Player __instance, bool __state)
	{
		if (__state && (Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.MarkProgressDirty(__instance);
		}
	}
}
[HarmonyPatch(typeof(Player), "AddKnownRecipe")]
internal static class KnownRecipePatch
{
	private static void Prefix(Player __instance, Recipe __0, out bool __state)
	{
		__state = (Object)(object)__0 != (Object)null && (Object)(object)__0.m_item != (Object)null && !__instance.IsRecipeKnown(__0.m_item.m_itemData.m_shared.m_name);
	}

	private static void Postfix(Player __instance, bool __state)
	{
		if (__state && (Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.MarkProgressDirty(__instance);
		}
	}
}
[HarmonyPatch(typeof(Player), "ResetCharacterKnownItems")]
internal static class ResetKnownItemsPatch
{
	private static void Postfix(Player __instance)
	{
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.MarkProgressDirty(__instance);
		}
	}
}
[HarmonyPatch(typeof(Player), "TakeInput")]
internal static class PlayerInputPatch
{
	private static bool Prefix(ref bool __result)
	{
		if (!Plugin.BlocksInput)
		{
			return true;
		}
		__result = false;
		return false;
	}
}
[HarmonyPatch(typeof(InventoryGui), "IsVisible")]
internal static class InventoryVisiblePatch
{
	private static void Postfix(ref bool __result)
	{
		if (Plugin.BlocksInput)
		{
			__result = true;
		}
	}
}
[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
internal static class CursorPatch
{
	private static void Postfix()
	{
		if (Plugin.IsOpen)
		{
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}
	}
}
[HarmonyPatch(typeof(Menu), "Update")]
internal static class MenuPatch
{
	private static bool Prefix()
	{
		return !Plugin.BlocksInput;
	}
}
public static class RollMath
{
	public static double Chance(double stake, double target, double returnRate, double maximum, double upgradeExponent = 1.25)
	{
		if (!FinitePositive(stake) || !FinitePositive(target))
		{
			return 0.0;
		}
		if (!FinitePositive(returnRate) || !FinitePositive(maximum))
		{
			return 0.0;
		}
		if (!FinitePositive(upgradeExponent))
		{
			return 0.0;
		}
		double num = stake / target;
		double num2 = ((num < 1.0) ? Math.Pow(num, Math.Max(1.0, upgradeExponent)) : num);
		return Math.Min(Math.Min(maximum, 1.0), num2 * Math.Min(returnRate, 1.0));
	}

	public static bool FinitePositive(double value)
	{
		if (value > 0.0 && !double.IsInfinity(value))
		{
			return !double.IsNaN(value);
		}
		return false;
	}

	public static bool Wins(double sample, double chance)
	{
		if (sample >= 0.0 && sample < 1.0)
		{
			return sample < chance;
		}
		return false;
	}

	public static double EndAngle(double sample)
	{
		return sample * 360.0;
	}

	public static double TargetValue(double unitValue, int amount)
	{
		if (amount <= 0 || !FinitePositive(unitValue))
		{
			return 0.0;
		}
		return unitValue * (double)amount;
	}

	public static double SmoothSpin(double t)
	{
		t = Math.Max(0.0, Math.Min(1.0, t));
		if (t < 0.12)
		{
			return 0.5 * (t - 3.0 / (25.0 * Math.PI) * Math.Sin(Math.PI * t / 0.12)) / 0.62;
		}
		double num = 0.06;
		if (t < 0.36)
		{
			return (num + t - 0.12) / 0.62;
		}
		double num2 = t - 0.36;
		double num3 = 0.64;
		return (num + 0.36 - 0.12 + 0.5 * (num2 + num3 / Math.PI * Math.Sin(Math.PI * num2 / num3))) / 0.62;
	}

	public static string Percent(double chance)
	{
		double num = chance * 100.0;
		if (num >= 0.01)
		{
			return num.ToString("0.00", CultureInfo.InvariantCulture) + "%";
		}
		if (num > 0.0)
		{
			return num.ToString((num < 1E-08) ? "0.###E+0" : "0.########", CultureInfo.InvariantCulture) + "%";
		}
		return "0%";
	}
}
public sealed class UpgraderUI
{
	private sealed class CardView
	{
		public RectTransform Root;

		public Image Icon;

		public Image Background;

		public FrameGraphic Frame;

		public Button Button;

		public Text First;

		public Text Second;

		public CatalogItem Entry;

		public ItemData Item;

		public string Tooltip;

		public int Index = -1;

		public void SetSelected(bool selected)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			((Graphic)Background).color = (Color)(selected ? new Color(0.3f, 0.22f, 0.11f, 1f) : Card);
			((Graphic)Frame).color = (selected ? Gold : Border);
		}
	}

	private readonly Plugin plugin;

	private GameObject root;

	private RectTransform panel;

	private RectTransform needle;

	private Font font;

	private WheelGraphic wheel;

	private Text sourceName;

	private Text sourceValue;

	private Text sourceQuality;

	private Text sourceQty;

	private Text targetName;

	private Text targetValue;

	private Text targetQuality;

	private Text percent;

	private Text status;

	private Text footer;

	private Text catalogCount;

	private Image sourceIcon;

	private Image targetIcon;

	private Button roll;

	private Button claim;

	private Button minus;

	private Button plus;

	private Button all;

	private Button clear;

	private Button reload;

	private Button category;

	private Button targetMinus;

	private Button targetPlus;

	private Text rollLabel;

	private Text claimLabel;

	private Text categoryLabel;

	private Text catalogEmpty;

	private InputField search;

	private InputField targetQuantity;

	private Toggle showAll;

	private RectTransform targetQuantityGroup;

	private ScrollRect inventoryScroll;

	private ScrollRect catalogScroll;

	private RectTransform inventoryContent;

	private RectTransform catalogContent;

	private readonly List<CardView> inventoryCards = new List<CardView>();

	private readonly List<CardView> targetCards = new List<CardView>();

	private readonly List<CatalogItem> matches = new List<CatalogItem>();

	private List<ItemData> inventoryItems = new List<ItemData>();

	private int inventoryStamp = int.MinValue;

	private bool catalogBound;

	private int progressRevision = -1;

	private int filter;

	private bool lastVisible;

	private bool previousCursorVisible;

	private CursorLockMode previousCursorLock;

	private string footerDefault;

	private int languageRevision = -1;

	private CardView hoveredCard;

	private readonly List<KeyValuePair<Text, TextKey>> localizedLabels = new List<KeyValuePair<Text, TextKey>>();

	private static readonly TextKey[] Categories = new TextKey[4]
	{
		TextKey.CategoryAll,
		TextKey.CategoryEquipment,
		TextKey.CategoryResources,
		TextKey.CategoryFood
	};

	private static readonly Color Background = new Color(0.055f, 0.068f, 0.083f, 0.985f);

	private static readonly Color Card = new Color(0.085f, 0.1f, 0.12f, 1f);

	private static readonly Color Border = new Color(0.29f, 0.26f, 0.19f, 1f);

	private static readonly Color Gold = new Color(0.96f, 0.68f, 0.24f, 1f);

	private static readonly Color TextColor = new Color(0.91f, 0.91f, 0.87f, 1f);

	private static readonly Color Muted = new Color(0.56f, 0.59f, 0.61f, 1f);

	private static readonly Color Green = new Color(0.4f, 0.85f, 0.56f, 1f);

	public bool Visible
	{
		get
		{
			if ((Object)(object)root != (Object)null)
			{
				return root.activeSelf;
			}
			return false;
		}
	}

	public UpgraderUI(Plugin plugin)
	{
		this.plugin = plugin;
		try
		{
			font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
		}
		catch
		{
		}
		if ((Object)(object)font == (Object)null)
		{
			try
			{
				font = Resources.GetBuiltinResource<Font>("Arial.ttf");
			}
			catch
			{
			}
		}
		if ((Object)(object)font == (Object)null)
		{
			font = ((IEnumerable<Font>)Resources.FindObjectsOfTypeAll<Font>()).FirstOrDefault((Func<Font, bool>)((Font f) => (Object)(object)f != (Object)null && f.HasCharacter('Я')));
		}
		if ((Object)(object)font == (Object)null)
		{
			throw new InvalidOperationException("No UI font available");
		}
		Build();
		root.SetActive(false);
	}

	private void Build()
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: 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_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: 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_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0328: 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_0436: Unknown result type (might be due to invalid IL or missing references)
		//IL_048a: 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)
		//IL_0558: Unknown result type (might be due to invalid IL or missing references)
		root = new GameObject("ItemUpgrader", new Type[4]
		{
			typeof(RectTransform),
			typeof(Canvas),
			typeof(CanvasScaler),
			typeof(GraphicRaycaster)
		});
		Object.DontDestroyOnLoad((Object)(object)root);
		Canvas component = root.GetComponent<Canvas>();
		component.renderMode = (RenderMode)0;
		component.sortingOrder = 30000;
		CanvasScaler component2 = root.GetComponent<CanvasScaler>();
		component2.uiScaleMode = (ScaleMode)1;
		component2.referenceResolution = new Vector2(1600f, 900f);
		component2.matchWidthOrHeight = 0.5f;
		RectTransform obj = Rect(root.transform, "Shade", 0f, 0f, 1600f, 900f);
		obj.anchorMin = Vector2.zero;
		obj.anchorMax = Vector2.one;
		obj.sizeDelta = Vector2.zero;
		Paint(obj, new Color(0f, 0f, 0f, 0.67f), raycast: true);
		panel = Rect(root.transform, "Panel", 0f, 0f, 1080f, 820f);
		Paint(panel, Background, raycast: true);
		Outline(panel, Border, 2f);
		Label((Transform)(object)panel, "Title", TextKey.Title, 0f, 374f, 850f, 44f, 27, Gold, (TextAnchor)4);
		Label((Transform)(object)panel, "Subtitle", TextKey.Subtitle, 115f, 342f, 760f, 25f, 12, Muted, (TextAnchor)4);
		BuildProgressToggle();
		Action((Transform)(object)panel, "Close", "×", 505f, 375f, 38f, 38f, delegate
		{
			Hide();
		}, 24);
		Line((Transform)(object)panel, 0f, 325f, 1016f, Border);
		BuildSource();
		BuildTarget();
		BuildWheel();
		roll = Action((Transform)(object)panel, "Upgrade", TextKey.Upgrade, 0f, 29f, 350f, 48f, delegate
		{
			plugin.Roll();
		}, 20, accent: true);
		rollLabel = ((Component)roll).GetComponentInChildren<Text>();
		status = Label((Transform)(object)panel, "Status", "", 0f, -20f, 1000f, 42f, 14, Muted, (TextAnchor)4);
		Line((Transform)(object)panel, 0f, -48f, 1016f, Border);
		Label((Transform)(object)panel, "InventoryTitle", TextKey.InventoryTitle, -265f, -72f, 488f, 30f, 15, Gold, (TextAnchor)3);
		Label((Transform)(object)panel, "CatalogTitle", TextKey.CatalogTitle, 265f, -72f, 488f, 30f, 15, Gold, (TextAnchor)3);
		inventoryScroll = Scroll((Transform)(object)panel, "Inventory", -265f, -226f, 500f, 272f, out inventoryContent, new Vector2(57f, 66f), 8);
		search = Search((Transform)(object)panel, 195f, -113f, 356f, 32f);
		((UnityEvent<string>)(object)search.onValueChanged).AddListener((UnityAction<string>)delegate
		{
			RebuildTargets();
		});
		category = Action((Transform)(object)panel, "Category", TextKey.CategoryAll, 450f, -113f, 135f, 32f, CycleCategory, 12);
		categoryLabel = ((Component)category).GetComponentInChildren<Text>();
		catalogScroll = Scroll((Transform)(object)panel, "Catalog", 265f, -253f, 500f, 218f, out catalogContent, new Vector2(116f, 92f), 4);
		((UnityEvent<Vector2>)(object)catalogScroll.onValueChanged).AddListener((UnityAction<Vector2>)delegate
		{
			UpdateVisibleTargets();
		});
		catalogEmpty = Label((Transform)(object)panel, "EmptyCatalog", "", 265f, -246f, 460f, 90f, 14, Muted, (TextAnchor)4);
		catalogCount = Label((Transform)(object)panel, "Count", "", 255f, -383f, 180f, 22f, 11, Muted, (TextAnchor)5);
		reload = Action((Transform)(object)panel, "ReloadPrices", TextKey.ReloadPrices, 447f, -383f, 142f, 27f, delegate
		{
			plugin.ReloadValues();
		}, 10);
		footerDefault = ModText.Format(TextKey.Footer, plugin.HotkeyLabel);
		footer = Label((Transform)(object)panel, "Footer", footerDefault, -168f, -383f, 660f, 27f, 11, Muted, (TextAnchor)3);
	}

	private void BuildProgressToggle()
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Rect((Transform)(object)panel, "ShowAllItems", -393f, 340f, 230f, 24f);
		Paint(val, new Color(0f, 0f, 0f, 0f), raycast: true);
		RectTransform obj = Rect((Transform)(object)val, "Checkbox", -104f, 0f, 18f, 18f);
		Image targetGraphic = Paint(obj, Card, raycast: true);
		Outline(obj, Border, 1f);
		Image graphic = Paint(Rect((Transform)(object)obj, "Check", 0f, 0f, 10f, 10f), Gold);
		Label((Transform)(object)val, "Label", TextKey.AllItems, 11f, 0f, 202f, 24f, 12, TextColor, (TextAnchor)3);
		showAll = ((Component)val).gameObject.AddComponent<Toggle>();
		((Selectable)showAll).targetGraphic = (Graphic)(object)targetGraphic;
		showAll.graphic = (Graphic)(object)graphic;
		Navigation navigation = ((Selectable)showAll).navigation;
		((Navigation)(ref navigation)).mode = (Mode)0;
		((Selectable)showAll).navigation = navigation;
		showAll.SetIsOnWithoutNotify(false);
		((UnityEvent<bool>)(object)showAll.onValueChanged).AddListener((UnityAction<bool>)delegate(bool enabled)
		{
			plugin.SetShowAllItems(enabled);
		});
	}

	private void BuildSource()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: 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_0198: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Rect((Transform)(object)panel, "SourceSlot", -350f, 199f, 264f, 246f);
		Paint(val, Card);
		Outline(val, Border, 1f);
		Label((Transform)(object)val, "Caption", TextKey.StakeCaption, 0f, 98f, 240f, 25f, 13, Muted, (TextAnchor)4);
		RectTransform rect = Rect((Transform)(object)val, "ItemIcon", 0f, 43f, 64f, 64f);
		sourceIcon = Paint(rect, Color.white);
		sourceIcon.preserveAspect = true;
		sourceName = Label((Transform)(object)val, "Name", TextKey.ChooseSource, 0f, -7f, 242f, 34f, 15, TextColor, (TextAnchor)4);
		sourceValue = Label((Transform)(object)val, "Value", TextKey.EmptyValue, 0f, -39f, 240f, 24f, 14, Gold, (TextAnchor)4);
		sourceQuality = Label((Transform)(object)val, "Quality", TextKey.QualityLimit, 0f, -63f, 236f, 18f, 10, Muted, (TextAnchor)4);
		minus = Action((Transform)(object)val, "Minus", "−", -92f, -91f, 31f, 31f, delegate
		{
			plugin.SetQuantity(plugin.Quantity - 1);
		}, 18);
		sourceQty = Label((Transform)(object)val, "Quantity", "× 1", -25f, -91f, 80f, 31f, 15, TextColor, (TextAnchor)4);
		plus = Action((Transform)(object)val, "Plus", "+", 43f, -91f, 31f, 31f, delegate
		{
			plugin.SetQuantity(plugin.Quantity + 1);
		}, 18);
		all = Action((Transform)(object)val, "All", TextKey.StackAll, 92f, -91f, 51f, 31f, delegate
		{
			if (plugin.Source != null)
			{
				plugin.SetQuantity(plugin.Source.m_stack);
			}
		}, 10);
		clear = Action((Transform)(object)val, "Clear", "×", 108f, 97f, 23f, 23f, delegate
		{
			plugin.ClearSource();
		}, 14);
	}

	private void BuildTarget()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: 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)
		RectTransform val = Rect((Transform)(object)panel, "TargetSlot", 350f, 199f, 264f, 246f);
		Paint(val, Card);
		Outline(val, Border, 1f);
		Label((Transform)(object)val, "Caption", TextKey.TargetCaption, 0f, 98f, 240f, 25f, 13, Muted, (TextAnchor)4);
		RectTransform rect = Rect((Transform)(object)val, "ItemIcon", 0f, 43f, 64f, 64f);
		targetIcon = Paint(rect, Color.white);
		targetIcon.preserveAspect = true;
		targetName = Label((Transform)(object)val, "Name", TextKey.ChooseTarget, 0f, -7f, 242f, 34f, 15, TextColor, (TextAnchor)4);
		targetValue = Label((Transform)(object)val, "Value", TextKey.EmptyValue, 0f, -39f, 240f, 24f, 14, Gold, (TextAnchor)4);
		targetQuality = Label((Transform)(object)val, "Quality", TextKey.QualityOne, 0f, -63f, 236f, 18f, 10, Muted, (TextAnchor)4);
		claim = Action((Transform)(object)val, "Claim", TextKey.Claim, 0f, -91f, 218f, 31f, delegate
		{
			plugin.Claim();
		}, 13, accent: true);
		claimLabel = ((Component)claim).GetComponentInChildren<Text>();
		((Component)claim).gameObject.SetActive(false);
		targetQuantityGroup = Rect((Transform)(object)val, "QuantityControls", 0f, -91f, 218f, 31f);
		targetMinus = Action((Transform)(object)targetQuantityGroup, "Minus", "−", -85f, 0f, 31f, 31f, delegate
		{
			plugin.SetTargetQuantity(plugin.TargetQuantity - 1);
		}, 18);
		targetPlus = Action((Transform)(object)targetQuantityGroup, "Plus", "+", 85f, 0f, 31f, 31f, delegate
		{
			plugin.SetTargetQuantity(plugin.TargetQuantity + 1);
		}, 18);
		targetQuantity = Search((Transform)(object)targetQuantityGroup, 0f, 0f, 108f, 31f, TextKey.Quantity);
		targetQuantity.contentType = (ContentType)2;
		targetQuantity.characterLimit = 5;
		targetQuantity.textComponent.alignment = (TextAnchor)4;
		((UnityEvent<string>)(object)targetQuantity.onValueChanged).AddListener((UnityAction<string>)delegate(string value)
		{
			if (int.TryParse(value, out var result) && result > 0)
			{
				plugin.SetTargetQuantity(result);
				if (result > plugin.MaximumRewardAmount)
				{
					targetQuantity.SetTextWithoutNotify(plugin.MaximumRewardAmount.ToString());
				}
			}
		});
		((UnityEvent<string>)(object)targetQuantity.onEndEdit).AddListener((UnityAction<string>)delegate(string value)
		{
			plugin.SetTargetQuantity((!int.TryParse(value, out var result)) ? 1 : result);
			targetQuantity.SetTextWithoutNotify(plugin.TargetQuantity.ToString());
		});
	}

	private void BuildWheel()
	{
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Rect((Transform)(object)panel, "Wheel", 0f, 185f, 260f, 260f);
		wheel = ((Component)val).gameObject.AddComponent<WheelGraphic>();
		((Graphic)wheel).raycastTarget = false;
		needle = Rect((Transform)(object)val, "Needle", 0f, 0f, 260f, 260f);
		RectTransform obj = Rect((Transform)(object)needle, "Shaft", 0f, 0f, 2f, 119f);
		obj.pivot = new Vector2(0.5f, 0f);
		Paint(obj, new Color(0.96f, 0.91f, 0.73f, 1f));
		((Graphic)((Component)Rect((Transform)(object)needle, "ArrowTip", 0f, 116f, 16f, 18f)).gameObject.AddComponent<ArrowGraphic>()).color = Gold;
		((Graphic)((Component)Rect((Transform)(object)val, "Center", 0f, 0f, 156f, 156f)).gameObject.AddComponent<DiskGraphic>()).color = Background;
		percent = Label((Transform)(object)val, "Percent", "—", 0f, 8f, 154f, 46f, 29, Gold, (TextAnchor)4);
		Label((Transform)(object)val, "ChanceLabel", TextKey.ChanceLabel, 0f, -27f, 150f, 25f, 11, Muted, (TextAnchor)4);
	}

	public void Show()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		if (!Visible)
		{
			previousCursorVisible = Cursor.visible;
			previousCursorLock = Cursor.lockState;
			lastVisible = true;
		}
		root.SetActive(true);
		Cursor.lockState = (CursorLockMode)0;
		Cursor.visible = true;
		Refresh(force: true);
	}

	public void Hide()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		if (Visible)
		{
			Plugin.JustClosed();
		}
		hoveredCard = null;
		if ((Object)(object)root != (Object)null)
		{
			root.SetActive(false);
		}
		if ((Object)(object)EventSystem.current != (Object)null)
		{
			EventSystem.current.SetSelectedGameObject((GameObject)null);
		}
		if (lastVisible)
		{
			Cursor.lockState = previousCursorLock;
			Cursor.visible = previousCursorVisible;
			lastVisible = false;
		}
	}

	public void Destroy()
	{
		Hide();
		if ((Object)(object)root != (Object)null)
		{
			Object.Destroy((Object)(object)root);
		}
		root = null;
	}

	public void SetAngle(float degrees)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)needle != (Object)null)
		{
			((Transform)needle).localRotation = Quaternion.Euler(0f, 0f, 0f - degrees);
		}
	}

	public void ResetWheel()
	{
		SetAngle(0f);
		wheel.ClearResult();
	}

	public void ShowResult(bool won)
	{
		wheel.SetResult(won);
	}

	public void Refresh(bool force)
	{
		//IL_0525: Unknown result type (might be due to invalid IL or missing references)
		//IL_052c: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)root == (Object)null))
		{
			plugin.SyncLanguage();
			RefreshLanguage();
			plugin.RefreshProgress();
			categoryLabel.text = ModText.Get(Categories[filter]);
			showAll.SetIsOnWithoutNotify(plugin.ShowAllItems);
			((Selectable)showAll).interactable = !plugin.Spinning;
			ItemData source = plugin.Source;
			CatalogItem catalogItem = ((plugin.HasReward && !plugin.Spinning) ? plugin.RewardItem : plugin.Target);
			sourceName.text = ((source == null) ? ModText.Get(TextKey.ChooseSource) : (Name(source) + ((source.m_quality > 1) ? ("  ★" + source.m_quality) : "")));
			sourceValue.text = ((source == null) ? ModText.Get(TextKey.EmptyValue) : ModText.Format(TextKey.StakeValue, Number(plugin.Stake)));
			sourceQuality.text = ((source == null) ? ModText.Get(TextKey.QualityLimit) : ModText.Format(TextKey.QualityMultiplier, BalanceRules.QualityMultiplier(source.m_quality, source.m_shared.m_maxQuality).ToString("0.##", CultureInfo.InvariantCulture)));
			sourceQty.text = "× " + plugin.Quantity;
			SetIcon(sourceIcon, (source == null) ? null : source.GetIcon());
			targetName.text = ((catalogItem == null) ? ModText.Get(plugin.HasReward ? TextKey.SavedReward : TextKey.ChooseTarget) : catalogItem.Name);
			int amount = ((plugin.HasReward && !plugin.Spinning) ? plugin.RewardRemaining : plugin.TargetQuantity);
			targetValue.text = ((catalogItem == null) ? ModText.Get(TextKey.EmptyValue) : ModText.Format(TextKey.TargetValue, Number(RollMath.TargetValue(catalogItem.Value, amount))));
			targetQuality.text = ((catalogItem == null) ? ModText.Get(TextKey.QualityOne) : ModText.Format(TextKey.UnitValue, Number(catalogItem.Value)));
			SetIcon(targetIcon, (catalogItem == null) ? null : catalogItem.Template.GetIcon());
			((Component)claim).gameObject.SetActive(plugin.HasReward && !plugin.Spinning);
			((Selectable)claim).interactable = plugin.HasReward && !plugin.Spinning;
			claimLabel.text = ModText.Format(TextKey.ClaimAmount, plugin.RewardRemaining);
			((Component)targetQuantityGroup).gameObject.SetActive(!((Component)claim).gameObject.activeSelf);
			bool canChangeSelection = plugin.CanChangeSelection;
			((Selectable)targetMinus).interactable = canChangeSelection && plugin.Target != null && plugin.TargetQuantity > 1;
			((Selectable)targetPlus).interactable = canChangeSelection && plugin.Target != null && plugin.TargetQuantity < plugin.MaximumRewardAmount;
			((Selectable)targetQuantity).interactable = canChangeSelection && plugin.Target != null;
			if (!targetQuantity.isFocused)
			{
				targetQuantity.SetTextWithoutNotify(plugin.TargetQuantity.ToString());
			}
			((Selectable)minus).interactable = canChangeSelection && source != null && plugin.Quantity > 1;
			((Selectable)plus).interactable = canChangeSelection && source != null && plugin.Quantity < source.m_stack;
			((Selectable)all).interactable = canChangeSelection && source != null && plugin.Quantity < source.m_stack;
			((Selectable)clear).interactable = canChangeSelection && source != null;
			((Selectable)roll).interactable = plugin.CanRoll();
			rollLabel.text = ModText.Get(plugin.Spinning ? TextKey.SpinningButton : (plugin.HasReward ? TextKey.ClaimFirst : TextKey.Upgrade));
			((Selectable)reload).interactable = !plugin.Spinning;
			status.text = plugin.Status;
			((Graphic)status).color = ((plugin.HasReward && !plugin.Spinning) ? Green : Muted);
			double displayChance = plugin.DisplayChance;
			percent.text = ((displayChance <= 0.0) ? "—" : RollMath.Percent(displayChance));
			if (percent.text.Length > 8)
			{
				percent.fontSize = 17;
			}
			else
			{
				percent.fontSize = 29;
			}
			wheel.SetChance((float)displayChance);
			if (!plugin.Spinning && source != null)
			{
				wheel.ClearResult();
			}
			RebuildInventory();
			if (!catalogBound || progressRevision != plugin.ProgressRevision)
			{
				RebuildTargets();
			}
			else
			{
				UpdateVisibleTargets();
			}
			RefreshFooter();
		}
	}

	private void RefreshLanguage()
	{
		if (languageRevision == ModText.Revision)
		{
			return;
		}
		languageRevision = ModText.Revision;
		foreach (KeyValuePair<Text, TextKey> localizedLabel in localizedLabels)
		{
			localizedLabel.Key.text = ModText.Get(localizedLabel.Value);
		}
		footerDefault = ModText.Format(TextKey.Footer, plugin.HotkeyLabel);
		if (plugin.Catalog != null)
		{
			plugin.Catalog.SortItemsByName();
		}
		foreach (CardView targetCard in targetCards)
		{
			targetCard.Entry = null;
		}
		catalogBound = false;
	}

	private void RefreshFooter()
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		bool flag = hoveredCard != null && ((Component)hoveredCard.Root).gameObject.activeSelf;
		footer.text = (flag ? hoveredCard.Tooltip : footerDefault);
		((Graphic)footer).color = (flag ? TextColor : Muted);
	}

	public void RefreshCatalog()
	{
		inventoryStamp = int.MinValue;
		RebuildTargets();
		Refresh(force: false);
	}

	public IEnumerator Prewarm()
	{
		int targetCount = GridWindow.PoolSize(214.0, 96.0, 4);
		int inventoryCount = ((Humanoid)plugin.LocalPlayer).GetInventory().GetAllItems().Count;
		while (targetCards.Count < targetCount)
		{
			for (int i = 0; i < 4; i++)
			{
				if (targetCards.Count >= targetCount)
				{
					break;
				}
				targetCards.Add(CreateCard(target: true));
			}
			yield return null;
		}
		while (inventoryCards.Count < inventoryCount)
		{
			for (int j = 0; j < 4; j++)
			{
				if (inventoryCards.Count >= inventoryCount)
				{
					break;
				}
				inventoryCards.Add(CreateCard(target: false));
			}
			yield return null;
		}
		Refresh(force: false);
		int[] array = new int[4] { 10, 11, 15, 29 };
		foreach (int num in array)
		{
			font.RequestCharactersInTexture("АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя0123456789×%—.,:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", num);
			yield return null;
		}
	}

	private void RebuildInventory()
	{
		//IL_0159: 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)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)plugin.LocalPlayer == (Object)null)
		{
			return;
		}
		List<ItemData> allItems = ((Humanoid)plugin.LocalPlayer).GetInventory().GetAllItems();
		int num = 17;
		foreach (ItemData item in allItems)
		{
			num = num * 31 + ((object)item).GetHashCode();
			num = num * 31 + item.m_stack;
			num = num * 31 + item.m_quality;
			num = num * 31 + item.m_durability.GetHashCode();
			num = num * 31 + ((object)Unsafe.As<Vector2i, Vector2i>(ref item.m_gridPos)/*cast due to .constrained prefix*/).GetHashCode();
			num = num * 31 + (item.m_equipped ? 1 : 0);
		}
		if (num != inventoryStamp)
		{
			inventoryStamp = num;
			inventoryItems = (from i in allItems
				where plugin.Catalog.Find(i) != null
				orderby i.m_gridPos.y, i.m_gridPos.x
				select i).ToList();
			inventoryContent.sizeDelta = new Vector2(0f, (float)GridWindow.ContentHeight(inventoryItems.Count, 8, 66.0, 4.0));
		}
		while (inventoryCards.Count < inventoryItems.Count)
		{
			inventoryCards.Add(CreateCard(target: false));
		}
		for (int num2 = 0; num2 < inventoryCards.Count; num2++)
		{
			CardView cardView = inventoryCards[num2];
			if (num2 >= inventoryItems.Count)
			{
				((Component)cardView.Root).gameObject.SetActive(false);
				continue;
			}
			ItemData val = inventoryItems[num2];
			((Component)cardView.Root).gameObject.SetActive(true);
			cardView.Item = val;
			Position(cardView.Root, num2, 8, 57, 66);
			cardView.Icon.sprite = val.GetIcon();
			((Graphic)cardView.Icon).color = (Color)(val.m_equipped ? new Color(0.7f, 0.7f, 0.7f, 1f) : Color.white);
			cardView.First.text = "×" + val.m_stack;
			cardView.Second.text = (val.m_equipped ? "●" : "");
			cardView.Tooltip = ModText.Format(TextKey.SourceTooltip, Name(val), Number(plugin.Catalog.StakeValue(val, 1))) + (val.m_equipped ? ModText.Get(TextKey.UnequipTooltip) : "");
			((Selectable)cardView.Button).interactable = plugin.CanChangeSelection && !val.m_equipped && plugin.Catalog.Find(val) != null;
			cardView.SetSelected(plugin.Source == val);
		}
	}

	private void CycleCategory()
	{
		filter = (filter + 1) % 4;
		categoryLabel.text = ModText.Get(Categories[filter]);
		catalogScroll.verticalNormalizedPosition = 1f;
		RebuildTargets();
	}

	private bool MatchesFilter(CatalogItem entry)
	{
		string text = ((object)Unsafe.As<ItemType, ItemType>(ref entry.Template.m_shared.m_itemType)/*cast due to .constrained prefix*/).ToString();
		if (filter == 1)
		{
			if (!text.Contains("Weapon"))
			{
				switch (text)
				{
				default:
					return text == "Trinket";
				case "Bow":
				case "Shield":
				case "Helmet":
				case "Chest":
				case "Legs":
				case "Shoulder":
				case "Utility":
				case "Tool":
					break;
				}
			}
			return true;
		}
		if (filter == 2)
		{
			if (!(text == "Material") && !(text == "Trophy"))
			{
				return text == "Misc";
			}
			return true;
		}
		if (filter == 3)
		{
			if (!(text == "Consumable"))
			{
				return text == "Fish";
			}
			return true;
		}
		return true;
	}

	private void RebuildTargets()
	{
		//IL_011e: 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)
		if (plugin.Catalog == null || (Object)(object)catalogContent == (Object)null)
		{
			return;
		}
		string text = (((Object)(object)search == (Object)null) ? "" : search.text.Trim());
		matches.Clear();
		foreach (CatalogItem item in plugin.Catalog.Items)
		{
			if (plugin.CanChooseTarget(item) && MatchesFilter(item) && (text.Length == 0 || item.Name.IndexOf(text, StringComparison.CurrentCultureIgnoreCase) >= 0 || item.Id.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0))
			{
				matches.Add(item);
			}
		}
		catalogBound = true;
		progressRevision = plugin.ProgressRevision;
		catalogContent.sizeDelta = new Vector2(0f, (float)GridWindow.ContentHeight(matches.Count, 4, 92.0, 4.0));
		catalogContent.anchoredPosition = Vector2.zero;
		catalogScroll.StopMovement();
		int num = GridWindow.PoolSize(214.0, 96.0, 4);
		while (targetCards.Count < num)
		{
			targetCards.Add(CreateCard(target: true));
		}
		int num2 = (plugin.ShowAllItems ? plugin.Catalog.Items.Count : plugin.UnlockedItemCount);
		catalogCount.text = ModText.Format(plugin.ShowAllItems ? TextKey.CatalogTotal : TextKey.CatalogUnlocked, matches.Count, num2);
		((Component)catalogEmpty).gameObject.SetActive(matches.Count == 0);
		catalogEmpty.text = ModText.Get((!plugin.ShowAllItems && num2 == 0) ? TextKey.NothingUnlocked : TextKey.NoMatches);
		UpdateVisibleTargets();
	}

	private void UpdateVisibleTargets()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		int num = GridWindow.FirstIndex(catalogContent.anchoredPosition.y, 96.0, 4, matches.Count);
		for (int i = 0; i < targetCards.Count; i++)
		{
			CardView cardView = targetCards[i];
			int num2 = num + i;
			if (num2 >= matches.Count)
			{
				((Component)cardView.Root).gameObject.SetActive(false);
				cardView.Entry = null;
				continue;
			}
			CatalogItem catalogItem = matches[num2];
			((Component)cardView.Root).gameObject.SetActive(true);
			if (cardView.Index != num2)
			{
				Position(cardView.Root, num2, 4, 116, 92);
				cardView.Index = num2;
			}
			if (cardView.Entry != catalogItem)
			{
				cardView.Entry = catalogItem;
				cardView.Icon.sprite = catalogItem.Template.GetIcon();
				cardView.First.text = catalogItem.Name;
				cardView.Second.text = Number(catalogItem.Value);
				cardView.Tooltip = ModText.Format(TextKey.CatalogTooltip, catalogItem.Name, catalogItem.Id, Number(catalogItem.Value));
			}
			((Selectable)cardView.Button).interactable = plugin.CanChangeSelection && plugin.CanChooseTarget(catalogItem);
			cardView.SetSelected(plugin.Target == catalogItem);
		}
	}

	private CardView CreateCard(bool target)
	{
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Expected O, but got Unknown
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		CardView card = new CardView();
		card.Root = Rect((Transform)(object)(target ? catalogContent : inventoryContent), target ? "TargetCell" : "InventoryCell", 0f, 0f, target ? 116 : 57, target ? 92 : 66);
		RectTransform obj = card.Root;
		RectTransform obj2 = card.Root;
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor(0f, 1f);
		obj2.anchorMax = val;
		obj.anchorMin = val;
		card.Root.pivot = new Vector2(0f, 1f);
		card.Background = Paint(card.Root, Card, raycast: true);
		Outline(card.Root, Border, 1f);
		card.Frame = ((Component)((Transform)card.Root).Find("Frame")).GetComponent<FrameGraphic>();
		card.Button = ((Component)card.Root).gameObject.AddComponent<Button>();
		((Selectable)card.Button).targetGraphic = (Graphic)(object)card.Background;
		Navigation navigation = ((Selectable)card.Button).navigation;
		((Navigation)(ref navigation)).mode = (Mode)0;
		((Selectable)card.Button).navigation = navigation;
		((UnityEvent)card.Button.onClick).AddListener((UnityAction)delegate
		{
			if (target)
			{
				if (card.Entry != null)
				{
					plugin.SelectTarget(card.Entry);
				}
			}
			else if (card.Item != null)
			{
				plugin.SelectSource(card.Item);
			}
		});
		card.Icon = Paint(Rect((Transform)(object)card.Root, "Icon", 0f, target ? 22 : 8, target ? 30 : 36, target ? 30 : 36), Color.white);
		card.Icon.preserveAspect = true;
		card.First = Label((Transform)(object)card.Root, "First", "", 0f, target ? (-10) : (-21), target ? 108 : 54, target ? 32 : 18, 10, TextColor, (TextAnchor)4);
		card.Second = (target ? Label((Transform)(object)card.Root, "Second", "", 0f, -34f, 108f, 20f, 11, Gold, (TextAnchor)4) : Label((Transform)(object)card.Root, "Equipped", "", 18f, 21f, 16f, 16f, 10, Gold, (TextAnchor)4));
		ItemTip itemTip = ((Component)card.Root).gameObject.AddComponent<ItemTip>();
		itemTip.Enter = delegate
		{
			hoveredCard = card;
			RefreshFooter();
		};
		itemTip.Exit = delegate
		{
			if (hoveredCard == card)
			{
				hoveredCard = null;
			}
			RefreshFooter();
		};
		((Component)card.Root).gameObject.SetActive(false);
		return card;
	}

	private static void Position(RectTransform rect, int index, int columns, int width, int height)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		rect.anchoredPosition = new Vector2((float)(8 + index % columns * (width + 3)), (float)(-8 - index / columns * (height + 4)));
	}

	private static string Name(ItemData item)
	{
		if (Localization.instance != null)
		{
			return Localization.instance.Localize(item.m_shared.m_name);
		}
		return item.m_shared.m_name;
	}

	private static string Number(double value)
	{
		if (!(value >= 10000.0))
		{
			return value.ToString("0.##", CultureInfo.InvariantCulture);
		}
		return value.ToString("N0", CultureInfo.InvariantCulture);
	}

	private static void SetIcon(Image image, Sprite sprite)
	{
		image.sprite = sprite;
		((Behaviour)image).enabled = (Object)(object)sprite != (Object)null;
	}

	private static RectTransform Rect(Transform parent, string name, float x, float y, float width, float height)
	{
		//IL_0014: 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_003f: 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_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor(0.5f, 0.5f);
		component.anchorMax = val;
		component.anchorMin = val;
		component.pivot = new Vector2(0.5f, 0.5f);
		component.anchoredPosition = new Vector2(x, y);
		component.sizeDelta = new Vector2(width, height);
		return component;
	}

	private static Image Paint(RectTransform rect, Color color, bool raycast = false)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		Image obj = ((Component)rect).gameObject.AddComponent<Image>();
		((Graphic)obj).color = color;
		((Graphic)obj).raycastTarget = raycast;
		return obj;
	}

	private static void Outline(RectTransform rect, Color color, float thickness)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: 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)
		FrameGraphic frameGraphic = ((Component)Rect((Transform)(object)rect, "Frame", 0f, 0f, rect.sizeDelta.x, rect.sizeDelta.y)).gameObject.AddComponent<FrameGraphic>();
		((Graphic)frameGraphic).color = color;
		frameGraphic.Thickness = thickness;
		((Graphic)frameGraphic).raycastTarget = false;
	}

	private void Line(Transform parent, float x, float y, float width, Color color)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		Paint(Rect(parent, "Divider", x, y, width, 1f), color);
	}

	private Text Label(Transform parent, string name, TextKey key, float x, float y, float w, float h, int size, Color color, TextAnchor align)
	{
		//IL_0013: 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)
		Text val = Label(parent, name, ModText.Get(key), x, y, w, h, size, color, align);
		localizedLabels.Add(new KeyValuePair<Text, TextKey>(val, key));
		return val;
	}

	private Button Action(Transform parent, string name, TextKey key, float x, float y, float w, float h, Action callback, int size, bool accent = false)
	{
		Button val = Action(parent, name, ModText.Get(key), x, y, w, h, callback, size, accent);
		localizedLabels.Add(new KeyValuePair<Text, TextKey>(((Component)val).GetComponentInChildren<Text>(), key));
		return val;
	}

	private Text Label(Transform parent, string name, string text, float x, float y, float w, float h, int size, Color color, TextAnchor align)
	{
		//IL_0035: 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)
		Text obj = ((Component)Rect(parent, name, x, y, w, h)).gameObject.AddComponent<Text>();
		obj.font = font;
		obj.text = text;
		obj.fontSize = size;
		((Graphic)obj).color = color;
		obj.alignment = align;
		((Graphic)obj).raycastTarget = false;
		obj.supportRichText = false;
		obj.horizontalOverflow = (HorizontalWrapMode)0;
		obj.verticalOverflow = (VerticalWrapMode)0;
		return obj;
	}

	private Button Action(Transform parent, string name, string text, float x, float y, float w, float h, Action callback, int size, bool accent = false)
	{
		//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_006a: 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_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: 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_0128: Expected O, but got Unknown
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Rect(parent, name, x, y, w, h);
		Image targetGraphic = Paint(val, accent ? new Color(0.81f, 0.51f, 0.14f, 1f) : new Color(0.13f, 0.15f, 0.17f, 1f), raycast: true);
		Outline(val, accent ? Gold : Border, 1f);
		Button obj = ((Component)val).gameObject.AddComponent<Button>();
		((Selectable)obj).targetGraphic = (Graphic)(object)targetGraphic;
		ColorBlock colors = ((Selectable)obj).colors;
		((ColorBlock)(ref colors)).highlightedColor = new Color(1.17f, 1.17f, 1.17f, 1f);
		((ColorBlock)(ref colors)).pressedColor = new Color(0.72f, 0.72f, 0.72f, 1f);
		((ColorBlock)(ref colors)).disabledColor = new Color(0.6f, 0.6f, 0.6f, 0.65f);
		((Selectable)obj).colors = colors;
		Navigation navigation = ((Selectable)obj).navigation;
		((Navigation)(ref navigation)).mode = (Mode)0;
		((Selectable)obj).navigation = navigation;
		((UnityEvent)obj.onClick).AddListener((UnityAction)delegate
		{
			callback();
		});
		Label((Transform)(object)val, "Label", text, 0f, 0f, w - 8f, h - 4f, size, (Color)(accent ? new Color(0.14f, 0.09f, 0.03f, 1f) : TextColor), (TextAnchor)4);
		return obj;
	}

	private InputField Search(Transform parent, float x, float y, float w, float h, TextKey placeholderKey = TextKey.SearchPlaceholder)
	{
		//IL_0013: 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_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Rect(parent, "Search", x, y, w, h);
		Image targetGraphic = Paint(val, Card, raycast: true);
		Outline(val, Border, 1f);
		InputField obj = ((Component)val).gameObject.AddComponent<InputField>();
		((Selectable)obj).targetGraphic = (Graphic)(object)targetGraphic;
		obj.characterLimit = 64;
		Text val2 = Label((Transform)(object)val, "Text", "", 0f, 0f, w - 18f, h - 4f, 13, TextColor, (TextAnchor)3);
		val2.horizontalOverflow = (HorizontalWrapMode)1;
		obj.textComponent = val2;
		Text placeholder = Label((Transform)(object)val, "Placeholder", placeholderKey, 0f, 0f, w - 18f, h - 4f, 12, Muted, (TextAnchor)3);
		obj.placeholder = (Graphic)(object)placeholder;
		obj.lineType = (LineType)0;
		return obj;
	}

	private ScrollRect Scroll(Transform parent, string name, float x, float y, float width, float height, out RectTransform content, Vector2 cell, int columns)
	{
		//IL_0023: 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)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		RectTransform obj = Rect(parent, name, x, y, width, height);
		Paint(obj, new Color(0.035f, 0.044f, 0.054f, 1f), raycast: true);
		Outline(obj, Border, 1f);
		RowScrollRect rowScrollRect = ((Component)obj).gameObject.AddComponent<RowScrollRect>();
		((ScrollRect)rowScrollRect).horizontal = false;
		((ScrollRect)rowScrollRect).vertical = true;
		((ScrollRect)rowScrollRect).movementType = (MovementType)2;
		((ScrollRect)rowScrollRect).scrollSensitivity = (cell.y + 4f) * plugin.ScrollRowsPerNotch;
		RectTransform val = Rect((Transform)(object)obj, "Viewport", 0f, 0f, width - 4f, height - 4f);
		Paint(val, Color.white, raycast: true);
		((Component)val).gameObject.AddComponent<Mask>().showMaskGraphic = false;
		content = Rect((Transform)(object)val, "Content", 0f, 0f, width - 4f, height);
		content.anchorMin = new Vector2(0f, 1f);
		content.anchorMax = new Vector2(1f, 1f);
		content.pivot = new Vector2(0.5f, 1f);
		content.anchoredPosition = Vector2.zero;
		content.sizeDelta = new Vector2(0f, height);
		((ScrollRect)rowScrollRect).viewport = val;
		((ScrollRect)rowScrollRect).content = content;
		((ScrollRect)rowScrollRect).verticalNormalizedPosition = 1f;
		return (ScrollRect)(object)rowScrollRect;
	}
}
public sealed class RowScrollRect : ScrollRect
{
	public override void OnScroll(PointerEventData eventData)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: 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_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: 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)
		Vector2 scrollDelta = eventData.scrollDelta;
		float num = ((Mathf.Abs(scrollDelta.y) >= Mathf.Abs(scrollDelta.x)) ? scrollDelta.y : scrollDelta.x);
		if (Mathf.Abs(num) < 0.0001f)
		{
			return;
		}
		((ScrollRect)this).StopMovement();
		eventData.scrollDelta = new Vector2(0f, Mathf.Sign(num) * Mathf.Max(1f, Mathf.Abs(num)));
		try
		{
			((ScrollRect)this).OnScroll(eventData);
		}
		finally
		{
			eventData.scrollDelta = scrollDelta;
		}
	}
}
public sealed class FrameGraphic : MaskableGraphic
{
	public float Thickness = 1f;

	protected override void OnPopulateMesh(VertexHelper vh)
	{
		//IL_000c: 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)
		vh.Clear();
		Rect rect = ((Graphic)this).rectTransform.rect;
		float thickness = Thickness;
		Add(vh, ((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).xMax, ((Rect)(ref rect)).yMax);
		Add(vh, ((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin, ((Rect)(ref rect)).xMax, ((Rect)(ref rect)).yMin + thickness);
		Add(vh, ((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin + thickness, ((Rect)(ref rect)).xMin + thickness, ((Rect)(ref rect)).yMax - thickness);
		Add(vh, ((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).yMin + thickness, ((Rect)(ref rect)).xMax, ((Rect)(ref rect)).yMax - thickness);
	}

	private void Add(VertexHelper vh, float x0, float y0, float x1, float y1)
	{
		//IL_000a: 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_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_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: 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_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: 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)
		int currentVertCount = vh.currentVertCount;
		vh.AddVert(Vector2.op_Implicit(new Vector2(x0, y0)), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		vh.AddVert(Vector2.op_Implicit(new Vector2(x0, y1)), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		vh.AddVert(Vector2.op_Implicit(new Vector2(x1, y1)), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		vh.AddVert(Vector2.op_Implicit(new Vector2(x1, y0)), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		vh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);
		vh.AddTriangle(currentVertCount, currentVertCount + 2, currentVertCount + 3);
	}
}
public sealed class ItemTip : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
{
	public Action Enter;

	public Action Exit;

	public void OnPointerEnter(PointerEventData e)
	{
		if (Enter != null)
		{
			Enter();
		}
	}

	public void OnPointerExit(PointerEventData e)
	{
		if (Exit != null)
		{
			Exit();
		}
	}
}
public sealed class WheelGraphic : MaskableGraphic
{
	private float chance;

	private Color ticks = new Color(0.36f, 0.39f, 0.44f, 1f);

	public void SetChance(float value)
	{
		if (Math.Abs(chance - value) > 1E-08f)
		{
			chance = Mathf.Clamp01(value);
			((Graphic)this).SetVerticesDirty();
		}
	}

	public void SetResult(bool won)
	{
		//IL_0033: 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_0038: Unknown result type (might be due to invalid IL or missing references)
		ticks = (won ? new Color(0.4f, 0.85f, 0.56f, 1f) : new Color(0.78f, 0.3f, 0.22f, 1f));
		((Graphic)this).SetVerticesDirty();
	}

	public void ClearResult()
	{
		//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)
		ticks = new Color(0.36f, 0.39f, 0.44f, 1f);
		((Graphic)this).SetVerticesDirty();
	}

	protected override void OnPopulateMesh(VertexHelper vh)
	{
		//IL_000c: 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_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: 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_0129: 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: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: 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)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		vh.Clear();
		Rect rect = ((Graphic)this).rectTransform.rect;
		float width = ((Rect)(ref rect)).width;
		rect = ((Graphic)this).rectTransform.rect;
		float num = Mathf.Min(width, ((Rect)(ref rect)).height) / 2f;
		Arc(vh, num * 0.62f, num * 0.82f, 360f, new Color(0.17f, 0.2f, 0.25f, 1f));
		if (chance > 0f)
		{
			Arc(vh, num * 0.62f, num * 0.82f, chance * 360f, new Color(1f, 0.61f, 0.17f, 1f));
		}
		Vector2 val = default(Vector2);
		for (int i = 0; i < 60; i++)
		{
			float num2 = (float)i * (float)Math.PI * 2f / 60f;
			((Vector2)(ref val))..ctor(Mathf.Sin(num2), Mathf.Cos(num2));
			Vector2 val2 = new Vector2(val.y, 0f - val.x) * ((i % 5 == 0) ? 1.5f : 1f);
			Vector2 val3 = val * num * ((i % 5 == 0) ? 0.86f : 0.89f);
			Vector2 val4 = val * num * 0.95f;
			Quad(vh, val3 - val2, val3 + val2, val4 + val2, val4 - val2, ticks);
		}
	}

	private static void Arc(VertexHelper vh, float inner, float outer, float degrees, Color tint)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		int num = Math.Max(1, (int)Math.Ceiling(degrees / 2f));
		Vector2 val = default(Vector2);
		Vector2 val2 = default(Vector2);
		for (int i = 0; i < num; i++)
		{
			float num2 = degrees * (float)i / (float)num * ((float)Math.PI / 180f);
			float num3 = degrees * (float)(i + 1) / (float)num * ((float)Math.PI / 180f);
			((Vector2)(ref val))..ctor(Mathf.Sin(num2), Mathf.Cos(num2));
			((Vector2)(ref val2))..ctor(Mathf.Sin(num3), Mathf.Cos(num3));
			Quad(vh, val * inner, val * outer, val2 * outer, val2 * inner, tint);
		}
	}

	private static void Quad(VertexHelper vh, Vector2 a, Vector2 b, Vector2 c, Vector2 d, Color tint)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: 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_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_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_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: 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_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		int currentVertCount = vh.currentVertCount;
		vh.AddVert(Vector2.op_Implicit(a), Color32.op_Implicit(tint), Vector4.op_Implicit(Vector2.zero));
		vh.AddVert(Vector2.op_Implicit(b), Color32.op_Implicit(tint), Vector4.op_Implicit(Vector2.zero));
		vh.AddVert(Vector2.op_Implicit(c), Color32.op_Implicit(tint), Vector4.op_Implicit(Vector2.zero));
		vh.AddVert(Vector2.op_Implicit(d), Color32.op_Implicit(tint), Vector4.op_Implicit(Vector2.zero));
		vh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);
		vh.AddTriangle(currentVertCount, currentVertCount + 2, currentVertCount + 3);
	}
}
public sealed class ArrowGraphic : MaskableGraphic
{
	protected override void OnPopulateMesh(VertexHelper vh)
	{
		//IL_000c: 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_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_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_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: 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_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)
		vh.Clear();
		Rect rect = ((Graphic)this).rectTransform.rect;
		float num = ((Rect)(ref rect)).width / 2f;
		rect = ((Graphic)this).rectTransform.rect;
		float num2 = ((Rect)(ref rect)).height / 2f;
		vh.AddVert(Vector2.op_Implicit(new Vector2(0f, num2)), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		vh.AddVert(Vector2.op_Implicit(new Vector2(num, 0f - num2)), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		vh.AddVert(Vector2.op_Implicit(new Vector2(0f - num, 0f - num2)), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		vh.AddTriangle(0, 1, 2);
	}
}
public sealed class DiskGraphic : MaskableGraphic
{
	protected override void OnPopulateMesh(VertexHelper vh)
	{
		//IL_000c: 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_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//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_0049: 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_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: 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)
		vh.Clear();
		Rect rect = ((Graphic)this).rectTransform.rect;
		float width = ((Rect)(ref rect)).width;
		rect = ((Graphic)this).rectTransform.rect;
		float num = Mathf.Min(width, ((Rect)(ref rect)).height) / 2f;
		vh.AddVert(Vector2.op_Implicit(Vector2.zero), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		for (int i = 0; i <= 64; i++)
		{
			float num2 = (float)i * (float)Math.PI * 2f / 64f;
			vh.AddVert(Vector2.op_Implicit(new Vector2(Mathf.Cos(num2), Mathf.Sin(num2)) * num), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		}
		for (int j = 1; j <= 64; j++)
		{
			vh.AddTriangle(0, j, j + 1);
		}
	}
}
public sealed class CatalogItem
{
	public string Id;

	public GameObject Prefab;

	public ItemData Template;

	public double Value;

	public double RawCost;

	public int Tier;

	public string Reason;

	public bool Obtainable;

	public bool Craftable;

	private string localizedName;

	private int nameRevision = -1;

	public string Name
	{
		get
		{
			if (Localization.instance == null)
			{
				return Id;
			}
			if (localizedName == null || nameRevision != ModText.Revision)
			{
				localizedName = Localization.instance.Localize(Template.m_shared.m_name);
				nameRevision = ModText.Revision;
			}
			return localizedName;
		}
	}
}
public sealed class ValueCatalog
{
	private sealed class ProcessingRecipe
	{
		public string From;

		public string Fuel;

		public string Station;

		public double FuelAmount;

		public double Effort;

		public int Yield = 1;
	}

	public readonly List<CatalogItem> Items = new List<CatalogItem>();

	private readonly Dictionary<string, CatalogItem> byId = new Dictionary<string, CatalogItem>(StringComparer.Ordinal);

	private Dictionary<string, double> prices;

	private readonly Dictionary<string, List<Recipe>> recipes = new Dictionary<string, List<Recipe>>();

	private readonly Dictionary<string, Recipe> legacyRecipes = new Dictionary<string, Recipe>();

	private readonly Dictionary<string, List<ProcessingRecipe>> processing = new Dictionary<string, List<ProcessingRecipe>>();

	private readonly HashSet<string> customPrices = new HashSet<string>(StringComparer.Ordinal);

	private readonly Dictionary<string, double> computed = new Dictionary<string, double>();

	private readonly Dictionary<string, double> rawCosts = new Dictionary<string, double>();

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

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

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

	private readonly HashSet<GameObject> worldPrefabs = new HashSet<GameObject>();

	private readonly string folder;

	private readonly ManualLogSource log;

	private readonly double markup;

	private readonly double equipmentFactor;

	private static readonly CultureInfo Inv = CultureInfo.InvariantCulture;

	public string PricePath => Path.Combine(folder, "ItemValues.json");

	private string SnapshotPath => Path.Combine(folder, "AutomaticValues.json");

	private string BalanceVersionPath => Path.Combine(folder, "BalanceVersion.txt");

	public ValueCatalog(string folder, double markup, double equipmentFactor, ManualLogSource log)
	{
		this.folder = folder;
		this.markup = markup;
		this.equipmentFactor = equipmentFactor;
		this.log = log;
	}

	public void Build()
	{
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Invalid comparison between Unknown and I4
		Items.Clear();
		byId.Clear();
		recipes.Clear();
		legacyRecipes.Clear();
		processing.Clear();
		computed.Clear();
		rawCosts.Clear();
		tiers.Clear();
		rawReasons.Clear();
		reasons.Clear();
		customPrices.Clear();
		prices = Defaults();
		Directory.CreateDirectory(folder);
		Dictionary<string, double> dictionary = null;
		if (File.Exists(PricePath))
		{
			dictionary = JsonConvert.DeserializeObject<Dictionary<string, double>>(File.ReadAllText(PricePath));
			if (dictionary == null)
			{
				throw new InvalidDataException("ItemValues.json must contain an object of prefab IDs and prices.");
			}
			foreach (KeyValuePair<string, double> item in dictionary)
			{
				if (item.Value < 0.0 || double.IsInfinity(item.Value) || double.IsNaN(item.Value))
				{
					throw new InvalidDataException("Invalid price for " + item.Key);
				}
			}
		}
		foreach (GameObject item2 in ObjectDB.instance.m_items)
		{
			if ((Object)(object)item2 == (Object)null)
			{
				continue;
			}
			ItemDrop component = item2.GetComponent<ItemDrop>();
			if (!((Object)(object)component == (Object)null) && component.m_itemData != null)
			{
				ItemData itemData = component.m_itemData;
				if (itemData.m_shared != null && !string.IsNullOrEmpty(itemData.m_shared.m_name) && itemData.m_shared.m_icons != null && itemData.m_shared.m_icons.Length != 0 && !((Object)(object)itemData.m_shared.m_icons[0] == (Object)null) && (int)itemData.m_shared.m_itemType != 0 && (int)itemData.m_shared.m_itemType != 10 && !byId.ContainsKey(((Object)item2).name))
				{
					CatalogItem catalogItem = new CatalogItem
					{
						Id = ((Object)item2).name,
						Prefab = item2,
						Template = itemData
					};
					byId.Add(catalogItem.Id, catalogItem);
				}
			}
		}
		foreach (Recipe recipe in ObjectDB.instance.m_recipes)
		{
			if ((Object)(object)recipe == (Object)null || !recipe.m_enabled || (Object)(object)recipe.m_item == (Object)null || recipe.m_amount <= 0)
			{
				continue;
			}
			string name = ((Object)((Component)recipe.m_item).gameObject).name;
			if (!legacyRecipes.ContainsKey(name))
			{
				legacyRecipes[name] = recipe;
			}
			if (!recipe.m_noCraftOnlyUpgrade)
			{
				if (!recipes.TryGetValue(name, out var value))
				{
					value = (recipes[name] = new List<Recipe>());
				}
				value.Add(recipe);
			}
		}
		CollectProcessingRecipes();
		ObtainableItems obtainableItems = new ObtainableItems();
		foreach (GameObject worldPrefab in worldPrefabs)
		{
			obtainableItems.IncludeWorldPrefab(worldPrefab);
		}
		foreach (Recipe recipe2 in ObjectDB.instance.m_recipes)
		{
			obtainableItems.IncludeRecipe(recipe2);
		}
		foreach (KeyValuePair<string, List<ProcessingRecipe>> item3 in processing)
		{
			foreach (ProcessingRecipe item4 in item3.Value)
			{
				obtainableItems.AddProcessing(item4.From, item3.Key);
			}
		}
		obtainableItems.ResolveProcessing();
		ApplyEdits(dictionary);
		BackupPreviousBalance(dictionary != null);
		Dictionary<string, double> dictionary2 = new Dictionary<string, double>(prices, StringComparer.Ordinal);
		foreach (CatalogItem value2 in byId.Values)
		{
			value2.Value = Math.Round(Resolve(value2.Id), 4);
			value2.RawCost = Math.Round(RawCost(value2.Id, new HashSet<string>()), 4);
			value2.Tier = Tier(value2.Id, new HashSet<string>());
			value2.Reason = (reasons.ContainsKey(value2.Id) ? reasons[value2.Id] : "Configured value");
			string dlc = value2.Template.m_shared.m_dlc;
			value2.Obtainable = obtainableItems.Contains(value2.Id) && (string.IsNullOrEmpty(dlc) || ((Object)(object)DLCMan.instance != (Object)null && DLCMan.instance.IsDLCInstalled(dlc)));
			value2.Craftable = recipes.ContainsKey(value2.Id);
			dictionary2[value2.Id] = value2.Value;
			if (value2.Value > 0.0 && value2.Obtainable)
			{
				Items.Add(value2);
			}
		}
		SortItemsByName();
		AtomicWrite(PricePath, JsonConvert.SerializeObject((object)dictionary2.OrderBy((KeyValuePair<string, double> p) => p.Key).ToDictionary((KeyValuePair<string, double> p) => p.Key, (KeyValuePair<string, double> p) => p.Value), (Formatting)1));
		AtomicWrite(SnapshotPath, JsonConvert.SerializeObject((object)(from p in dictionary2
			where !customPrices.Contains(p.Key)
			orderby p.Key
			select p).ToDictionary(