Decompiled source of MerchantStacker v1.0.1

MerchantStacker.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using InControl;
using MerchantStacker.Patches;
using Microsoft.CodeAnalysis;
using TMProOld;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MerchantStacker")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+8f0fc1654bce926d1feb93021b9281f4d06d4a57")]
[assembly: AssemblyProduct("MerchantStacker")]
[assembly: AssemblyTitle("MerchantStacker")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/RaincloudTheDragon/MerchantStacker")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace MerchantStacker
{
	internal static class Eligibility
	{
		public static bool IsStackableShopOffer(ShopItem? item)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			if (item.IsAvailableNotInfinite)
			{
				return false;
			}
			if (!IsBulkTypeFlags(item.GetTypeFlags()))
			{
				return false;
			}
			if (item.Cost <= 0)
			{
				return false;
			}
			return item.Item is CollectableItem;
		}

		private static bool IsBulkTypeFlags(TypeFlags flags)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Invalid comparison between Unknown and I4
			if ((int)flags != 0)
			{
				return (int)flags == 1;
			}
			return true;
		}

		public static bool StockHasStackableOffers(ShopMenuStock? stock)
		{
			if ((Object)(object)stock == (Object)null)
			{
				return false;
			}
			try
			{
				foreach (ShopItem item in ((ShopMenuStock)(((Object)(object)stock.MasterList != (Object)null) ? ((object)stock.MasterList) : ((object)stock))).EnumerateStock())
				{
					if (IsStackableShopOffer(item))
					{
						return true;
					}
				}
				int itemCount = stock.GetItemCount();
				for (int i = 0; i < itemCount; i++)
				{
					GameObject itemGameObject = stock.GetItemGameObject(i);
					ShopItemStats obj = ((itemGameObject != null) ? itemGameObject.GetComponent<ShopItemStats>() : null);
					if (IsStackableShopOffer((obj != null) ? obj.Item : null))
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		public static bool IsBulkEligible(ShopItem? item)
		{
			if ((Object)(object)item == (Object)null || !item.IsAvailable)
			{
				return false;
			}
			if (!IsStackableShopOffer(item))
			{
				return false;
			}
			SavedItem item2 = item.Item;
			CollectableItem val = (CollectableItem)(object)((item2 is CollectableItem) ? item2 : null);
			if (val == null)
			{
				return false;
			}
			if (((SavedItem)val).CanGetMore())
			{
				return !val.IsAtMax();
			}
			return false;
		}

		public static bool ShouldOfferBulkQty(ShopItem? item)
		{
			if (!IsBulkEligible(item) || (Object)(object)item == (Object)null)
			{
				return false;
			}
			return GetMaxQuantity(item) >= 2;
		}

		public static int GetMaxQuantity(ShopItem item)
		{
			SavedItem item2 = item.Item;
			CollectableItem val = (CollectableItem)(object)((item2 is CollectableItem) ? item2 : null);
			if (val == null)
			{
				return 0;
			}
			int roomUntilCap = GetRoomUntilCap(val);
			int affordableCount = GetAffordableCount(item);
			return Math.Max(0, Math.Min(roomUntilCap, affordableCount));
		}

		public static int GetRoomUntilCap(CollectableItem item)
		{
			if (!((SavedItem)item).CanGetMore() || item.IsAtMax())
			{
				return 0;
			}
			int collectedAmount = item.CollectedAmount;
			int num = TryGetCap(item);
			if (num > 0)
			{
				return Math.Max(0, num - collectedAmount);
			}
			return 99;
		}

		public static int GetAffordableCount(ShopItem item)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			int cost = item.Cost;
			if (cost <= 0)
			{
				return 0;
			}
			CurrencyType currencyType = item.CurrencyType;
			if ((int)currencyType != 0)
			{
				if ((int)currencyType == 1)
				{
					return PlayerData.instance.ShellShards / cost;
				}
				return 0;
			}
			return PlayerData.instance.geo / cost;
		}

		public static int GetAffordableCount(int unitCost, CurrencyType currency)
		{
			//IL_0006: 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_000b: Invalid comparison between Unknown and I4
			if (unitCost <= 0)
			{
				return 0;
			}
			if ((int)currency != 0)
			{
				if ((int)currency == 1)
				{
					return PlayerData.instance.ShellShards / unitCost;
				}
				return 0;
			}
			return PlayerData.instance.geo / unitCost;
		}

		private static int TryGetCap(CollectableItem item)
		{
			try
			{
				FieldInfo field = typeof(CollectableItem).GetField("customMaxAmount", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null)
				{
					int num = (int)field.GetValue(item);
					if (num > 0)
					{
						return num;
					}
				}
			}
			catch
			{
			}
			return 20;
		}
	}
	[BepInPlugin("io.github.raincloudthedragon.merchantstacker", "MerchantStacker", "1.0.0")]
	public class MerchantStackerPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "io.github.raincloudthedragon.merchantstacker";

		public const string PluginName = "MerchantStacker";

		public const string PluginVersion = "1.0.0";

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<int> DpadStep;

		internal static ConfigEntry<int> StickStep;

		internal static ConfigEntry<float> HoldInitialDelay;

		internal static ConfigEntry<float> HoldMinRepeat;

		internal static ConfigEntry<float> HoldAccel;

		private Harmony? _harmony;

		private GameObject? _pickerGo;

		internal static MerchantStackerPlugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable bulk-buy quantity submenu.");
			DpadStep = ((BaseUnityPlugin)this).Config.Bind<int>("Controls", "DpadStep", 1, "Quantity change for d-pad up/down.");
			StickStep = ((BaseUnityPlugin)this).Config.Bind<int>("Controls", "StickStep", 5, "Quantity change for right stick up/down.");
			HoldInitialDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "HoldInitialDelay", 0.35f, "Seconds before hold-repeat starts.");
			HoldMinRepeat = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "HoldMinRepeat", 0.05f, "Fastest hold-repeat interval in seconds.");
			HoldAccel = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "HoldAccel", 0.85f, "Multiply repeat interval by this each step while held (< 1 accelerates).");
			_pickerGo = new GameObject("MerchantStacker_QuantityPicker");
			Object.DontDestroyOnLoad((Object)(object)_pickerGo);
			((Object)_pickerGo).hideFlags = (HideFlags)61;
			_pickerGo.AddComponent<QuantityPicker>();
			_harmony = new Harmony("io.github.raincloudthedragon.merchantstacker");
			TryPatch(typeof(ShopSelectionCachePatches));
			TryPatch(typeof(ShopConfirmShowPatches));
			TryPatch(typeof(ShopConfirmListPatches));
			TryPatch(typeof(ConfirmDialogPatches));
			TryPatch(typeof(InventoryPaneInputPatches));
			TryPatch(typeof(ShopPurchasePatches));
			TryPatch(typeof(SimpleShopPatches));
			TryPatch(typeof(MachinePurchasePatches));
			Log.LogInfo((object)"MerchantStacker v1.0.0 loaded (F6 ScriptEngine reload supported).");
		}

		private void TryPatch(Type type)
		{
			try
			{
				_harmony.PatchAll(type);
				Log.LogInfo((object)("Patched " + type.Name));
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to patch {type.Name}: {arg}");
			}
		}

		private void OnDestroy()
		{
			try
			{
				QuantityPicker.Instance?.ShutdownForReload();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("QuantityPicker unload: " + ex.Message));
				}
			}
			if ((Object)(object)_pickerGo != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)_pickerGo);
				_pickerGo = null;
			}
			PurchaseBatcher.ClearPendingQuantity();
			PurchaseBatcher.ExpectingFsmPurchase = false;
			PurchaseBatcher.ClearShopPurchaseSuppression();
			try
			{
				InventoryPaneInput.IsInputBlocked = false;
			}
			catch
			{
			}
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"MerchantStacker unloaded.");
			}
		}
	}
	internal static class PurchaseBatcher
	{
		internal static int PendingQuantity { get; set; }

		internal static bool IsBatching { get; private set; }

		internal static bool BlockShopPurchases { get; private set; }

		internal static bool ExpectingFsmPurchase { get; set; }

		internal static void ClearPendingQuantity()
		{
			PendingQuantity = 0;
		}

		internal static int ConsumePendingQuantity()
		{
			int pendingQuantity = PendingQuantity;
			PendingQuantity = 0;
			return pendingQuantity;
		}

		internal static void BeginShopPurchaseBlock()
		{
			BlockShopPurchases = true;
		}

		internal static void EndShopPurchaseBlock()
		{
			BlockShopPurchases = false;
		}

		internal static void ClearShopPurchaseSuppression()
		{
			BlockShopPurchases = false;
		}

		internal static void BuyShopItem(ShopItemStats stats, int quantity, int subItemIndex, Action? onComplete)
		{
			if ((Object)(object)stats == (Object)null || (Object)(object)stats.Item == (Object)null)
			{
				onComplete?.Invoke();
				return;
			}
			IsBatching = true;
			try
			{
				int num = 0;
				for (int i = 0; i < quantity; i++)
				{
					if (!stats.CanBuy())
					{
						break;
					}
					if (stats.IsAtMax())
					{
						break;
					}
					if (!stats.Item.IsAvailable)
					{
						break;
					}
					stats.SetPurchased((Action)null, subItemIndex);
					num++;
				}
				MerchantStackerPlugin.Log.LogInfo((object)$"Bought {num}x {stats.Item.DisplayName}");
				if (num > 0)
				{
					BeginShopPurchaseBlock();
				}
			}
			finally
			{
				IsBatching = false;
			}
			onComplete?.Invoke();
		}

		internal static void BuyShopItem(ShopItem item, int quantity, int subItemIndex, Action? onComplete)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_003b: Invalid comparison between Unknown and I4
			if ((Object)(object)item == (Object)null)
			{
				onComplete?.Invoke();
				return;
			}
			IsBatching = true;
			try
			{
				int num = 0;
				for (int i = 0; i < quantity; i++)
				{
					if (!item.IsAvailable)
					{
						break;
					}
					if (item.IsAtMax())
					{
						break;
					}
					CurrencyType currencyType = item.CurrencyType;
					if (!(((int)currencyType == 0) ? (PlayerData.instance.geo >= item.Cost) : ((int)currencyType == 1 && PlayerData.instance.ShellShards >= item.Cost)))
					{
						break;
					}
					item.SetPurchased((Action)null, subItemIndex);
					num++;
				}
				MerchantStackerPlugin.Log.LogInfo((object)$"Bought {num}x {item.DisplayName}");
				if (num > 0)
				{
					BeginShopPurchaseBlock();
				}
			}
			finally
			{
				IsBatching = false;
			}
			onComplete?.Invoke();
		}
	}
	internal sealed class QuantityPicker : MonoBehaviour
	{
		private static readonly FieldInfo InstanceField = AccessTools.Field(typeof(DialogueYesNoBox), "_instance");

		private static readonly FieldInfo CurrentYesField = AccessTools.Field(typeof(YesNoBox), "currentYes");

		private static readonly FieldInfo CurrentNoField = AccessTools.Field(typeof(YesNoBox), "currentNo");

		private static readonly FieldInfo SelectedStateField = AccessTools.Field(typeof(YesNoBox), "selectedState");

		private static readonly MethodInfo DoEndMethod = AccessTools.Method(typeof(YesNoBox), "DoEnd", (Type[])null, (Type[])null);

		private static readonly FieldInfo RequiredCurrencyAmountField = AccessTools.Field(typeof(DialogueYesNoBox), "requiredCurrencyAmount");

		private static readonly FieldInfo CurrencyTextField = AccessTools.Field(typeof(DialogueYesNoBox), "currencyText");

		private static readonly FieldInfo InstantiatedItemsField = AccessTools.Field(typeof(DialogueYesNoBox), "instantiatedItems");

		private static readonly FieldInfo WillGetItemField = AccessTools.Field(typeof(DialogueYesNoBox), "willGetItem");

		private static readonly FieldInfo ItemTemplateField = AccessTools.Field(typeof(DialogueYesNoBox), "itemTemplate");

		private static readonly FieldInfo ItemsLayoutField = AccessTools.Field(typeof(DialogueYesNoBox), "itemsLayout");

		private static readonly FieldInfo ItemCostTextField = AccessTools.Field(typeof(ShopItemStats), "itemCostText");

		private static readonly FieldInfo TitleTextField = AccessTools.Field(typeof(ShopMenuStock), "titleText");

		private static readonly FieldInfo CostSpriteField = AccessTools.Field(typeof(ShopItemStats), "costSprite");

		private static readonly FieldInfo ItemSpriteField = AccessTools.Field(typeof(ShopItemStats), "itemSprite");

		private static readonly FieldInfo ScrollUpArrowField = AccessTools.Field(typeof(ScrollView), "upArrow");

		private static readonly FieldInfo ScrollDownArrowField = AccessTools.Field(typeof(ScrollView), "downArrow");

		private static Mesh? _cachedCaretMesh;

		private static Material? _cachedCaretMaterial;

		private static int _cachedCaretSortLayer;

		private static int _cachedCaretSortOrder;

		private static Sprite? _cachedArrowSprite;

		private static bool _arrowAssetsSearched;

		private bool _active;

		private bool _hijacked;

		private bool _inShop;

		private int _quantity = 1;

		private int _min = 1;

		private int _max = 1;

		private int _unitCost;

		private CurrencyType _currency;

		private string _title = "Buy";

		private CollectableItem? _item;

		private ShopItemStats? _shopStats;

		private Transform? _shopRoot;

		private string? _originalCostText;

		private TextMeshPro? _boundCostText;

		private ShopMenuStock? _boundStock;

		private string? _originalShopTitle;

		private GameObject? _hudRoot;

		private TextMeshPro? _hudQty;

		private TextMeshPro? _hudCost;

		private GameObject? _hudArrowUp;

		private GameObject? _hudArrowDown;

		private SpriteRenderer? _hudCurrencyIcon;

		private GameObject? _hiddenConfirmList;

		private GameObject? _hiddenConfirmMsg;

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

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

		private GameObject? _itemArtSprite;

		private GameObject? _itemArtName;

		private SpriteRenderer? _itemArtSpriteSr;

		private TextMeshPro? _itemArtNameTmp;

		private int _lastHudQty = int.MinValue;

		private int _lastHudTotal = int.MinValue;

		private bool _lastArrowUpOn;

		private bool _lastArrowDownOn;

		private float _maxRecalcTimer;

		private int _chromeKeepOffFrame;

		private MeshRenderer? _itemArtNameMr;

		private Vector3 _qtyLocal;

		private Vector3 _costLocal;

		private Vector3 _currencyLocal;

		private Vector3 _arrowUpLocal;

		private Vector3 _arrowDownLocal;

		private Vector3 _arrowUpBaseLocalScale = Vector3.one;

		private Vector3 _arrowDownBaseLocalScale = Vector3.one;

		private Quaternion _arrowUpLocalRot = Quaternion.identity;

		private Quaternion _arrowDownLocalRot = Quaternion.identity;

		private Action? _originalYes;

		private Action? _originalNo;

		private Action<int>? _onConfirm;

		private Action? _onCancel;

		private Action? _purchaseDone;

		private Action? _shopCancel;

		private float _upTimer;

		private float _downTimer;

		private float _upInterval;

		private float _downInterval;

		private bool _upHeld;

		private bool _downHeld;

		private int _heldStep;

		internal static QuantityPicker? Instance { get; private set; }

		internal static bool SuppressHijack { get; private set; }

		public bool IsOpen => _active;

		public int CurrentQuantity => _quantity;

		private void Awake()
		{
			Instance = this;
		}

		internal void ShutdownForReload()
		{
			SuppressHijack = false;
			try
			{
				if (_active)
				{
					if (_inShop)
					{
						AbortInShopSession(resetShopWindow: true);
					}
					else
					{
						Finish(confirmed: false);
					}
				}
				else
				{
					DestroyInShopHud(restoreTexts: true);
				}
			}
			catch (Exception ex)
			{
				MerchantStackerPlugin.Log.LogWarning((object)("QuantityPicker shutdown: " + ex.Message));
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		public void OpenInShop(Transform shopRoot, string title, CollectableItem? item, int unitCost, CurrencyType currency, int maxQuantity, ShopItemStats stats)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (MerchantStackerPlugin.Enabled.Value && maxQuantity >= 1 && !_active && !((Object)(object)((stats != null) ? stats.Item : null) == (Object)null))
			{
				BeginSession(title, item, unitCost, currency, maxQuantity, hijacked: false);
				_inShop = true;
				_shopRoot = shopRoot;
				_shopStats = stats;
				_onConfirm = null;
				_onCancel = null;
				BindShopCostText(stats);
				BuildConfirmQtyHud();
				if ((Object)(object)_hudRoot == (Object)null)
				{
					MerchantStackerPlugin.Log.LogWarning((object)"OpenInShop: HUD failed — restoring vanilla confirm");
					_active = false;
					_inShop = false;
					_shopRoot = null;
					_shopStats = null;
					InventoryPaneInput.IsInputBlocked = false;
					ShopConfirmListPatches.RestoreConfirmChromePublic();
				}
				else
				{
					RefreshInShopHud();
					((MonoBehaviour)this).StartCoroutine(EnsureHudSoon());
					MerchantStackerPlugin.Log.LogInfo((object)$"In-shop qty: {_title} max={_max} cost={_unitCost} hud=True");
				}
			}
		}

		public void ArmShopPurchaseSession(Action? onPurchaseComplete, Action? onCancelPurchase)
		{
			_purchaseDone = onPurchaseComplete;
			_shopCancel = onCancelPurchase;
		}

		private void LateUpdate()
		{
			if (_active && _inShop)
			{
				if ((++_chromeKeepOffFrame & 0xF) == 0)
				{
					KeepCachedItemArtVisible();
				}
				Transform val = (Transform)(((Object)(object)_shopRoot != (Object)null) ? ((object)_shopRoot) : ((object)(((Object)(object)_shopStats != (Object)null) ? ((Component)_shopStats).transform.root : null)));
				if ((Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)val) || !((Component)val).gameObject.activeInHierarchy)
				{
					AbortInShopSession(resetShopWindow: true);
				}
			}
		}

		private void KeepCachedChromeOff()
		{
			for (int i = 0; i < _chromeToKeepOff.Count; i++)
			{
				GameObject val = _chromeToKeepOff[i];
				if ((Object)(object)val != (Object)null && val.activeSelf)
				{
					val.SetActive(false);
				}
			}
		}

		private void KeepCachedItemArtVisible()
		{
			if ((Object)(object)_itemArtSprite != (Object)null && !_itemArtSprite.activeSelf)
			{
				_itemArtSprite.SetActive(true);
			}
			if ((Object)(object)_itemArtSpriteSr != (Object)null && !((Renderer)_itemArtSpriteSr).enabled)
			{
				((Renderer)_itemArtSpriteSr).enabled = true;
			}
			if ((Object)(object)_itemArtName != (Object)null && !_itemArtName.activeSelf)
			{
				_itemArtName.SetActive(true);
			}
			if ((Object)(object)_itemArtNameTmp != (Object)null)
			{
				if (!((Behaviour)_itemArtNameTmp).enabled)
				{
					((Behaviour)_itemArtNameTmp).enabled = true;
				}
				if ((Object)(object)_itemArtNameMr != (Object)null && !((Renderer)_itemArtNameMr).enabled)
				{
					((Renderer)_itemArtNameMr).enabled = true;
				}
			}
		}

		private void CacheChromeToKeepOff(Transform confirm, Transform? confirmGroup)
		{
			_chromeToKeepOff.Clear();
			Transform[] componentsInChildren = ((Component)(((Object)(object)confirmGroup != (Object)null) ? ((object)confirmGroup) : ((object)confirm))).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string name = ((Object)val).name;
				if (!(name == "UI List") || !((Object)(object)val.parent != (Object)null) || !(((Object)val.parent).name == "Confirm"))
				{
					switch (name)
					{
					case "Yes":
					case "No":
						if (!ShopConfirmListPatches.IsUnderShopConfirmPublic(val))
						{
							continue;
						}
						break;
					case "Confirm msg":
					case "Costs":
					case "Thankyou":
					case "Money":
					case "Item cost":
					case "Geo Sprite":
						break;
					default:
						continue;
					}
				}
				_chromeToKeepOff.Add(((Component)val).gameObject);
			}
			ShopConfirmShowPatches.LockConfirmChrome = true;
			KeepCachedChromeOff();
		}

		private void CacheItemArt(Transform layoutParent)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			_itemArtSprite = null;
			_itemArtName = null;
			_itemArtSpriteSr = null;
			_itemArtNameTmp = null;
			foreach (Transform item in layoutParent)
			{
				Transform val = item;
				if (!((Object)(object)val == (Object)null))
				{
					if (((Object)val).name == "Item Sprite")
					{
						_itemArtSprite = ((Component)val).gameObject;
						_itemArtSpriteSr = ((Component)val).GetComponent<SpriteRenderer>();
					}
					else if (((Object)val).name == "Item name")
					{
						_itemArtName = ((Component)val).gameObject;
						_itemArtNameTmp = ((Component)val).GetComponent<TextMeshPro>();
						_itemArtNameMr = (((Object)(object)_itemArtNameTmp != (Object)null) ? ((Component)_itemArtNameTmp).GetComponent<MeshRenderer>() : null);
					}
				}
			}
		}

		private Transform? GetShopMenuRoot()
		{
			try
			{
				if ((Object)(object)_shopStats != (Object)null)
				{
					return ((Component)_shopStats).transform.root;
				}
				if ((Object)(object)_shopRoot != (Object)null)
				{
					return _shopRoot.root;
				}
			}
			catch
			{
			}
			return null;
		}

		private void EnsureConfirmItemArtVisible()
		{
			Transform shopMenuRoot = GetShopMenuRoot();
			if ((Object)(object)shopMenuRoot == (Object)null)
			{
				return;
			}
			Transform val = FindNamedTransform(shopMenuRoot, "Item Confirm Group");
			if (!((Object)(object)val == (Object)null))
			{
				if (!((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(true);
				}
				CacheItemArt(val);
				KeepCachedItemArtVisible();
			}
		}

		private void AbortInShopSession(bool resetShopWindow)
		{
			if (_active)
			{
				MerchantStackerPlugin.Log.LogInfo((object)"In-shop qty aborted (shop closed/disabled)");
				PurchaseBatcher.ClearPendingQuantity();
				PurchaseBatcher.ExpectingFsmPurchase = false;
				PurchaseBatcher.ClearShopPurchaseSuppression();
				Action shopCancel = _shopCancel;
				_purchaseDone = null;
				_shopCancel = null;
				_active = false;
				_hijacked = false;
				_inShop = false;
				_shopRoot = null;
				_shopStats = null;
				DestroyInShopHud(restoreTexts: true);
				ResetHoldState();
				InventoryPaneInput.IsInputBlocked = false;
				if (resetShopWindow)
				{
					shopCancel?.Invoke();
				}
			}
		}

		public void Hijack(DialogueYesNoBox box, string title, CollectableItem? item, int unitCost, CurrencyType currency, int maxQuantity, Action? originalYes, Action? originalNo)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (MerchantStackerPlugin.Enabled.Value && maxQuantity >= 1 && !_active)
			{
				BeginSession(title, item, unitCost, currency, maxQuantity, hijacked: true);
				_inShop = false;
				_originalYes = originalYes;
				_originalNo = originalNo;
				_onConfirm = null;
				_onCancel = null;
				_purchaseDone = null;
				_shopCancel = null;
				CurrentYesField.SetValue(box, (Action)delegate
				{
					Finish(confirmed: true);
				});
				CurrentNoField.SetValue(box, (Action)delegate
				{
					Finish(confirmed: false);
				});
				EnsureWillGetDisplay(box, item);
				((MonoBehaviour)this).StartCoroutine(RefreshAfterOpen());
				MerchantStackerPlugin.Log.LogInfo((object)$"Hijack DialogueYesNoBox: {_title} max={_max} cost={_unitCost}");
			}
		}

		public void Open(string title, CollectableItem? item, int unitCost, CurrencyType currency, int maxQuantity, Action<int> onConfirm, Action onCancel)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if (!MerchantStackerPlugin.Enabled.Value || maxQuantity < 1)
			{
				onConfirm(1);
				return;
			}
			BeginSession(title, item, unitCost, currency, maxQuantity, hijacked: false);
			_inShop = false;
			_onConfirm = onConfirm;
			_onCancel = onCancel;
			_originalYes = null;
			_originalNo = null;
			_purchaseDone = null;
			_shopCancel = null;
			SuppressHijack = true;
			try
			{
				DialogueYesNoBox.Open((Action)delegate
				{
					Finish(confirmed: true);
				}, (Action)delegate
				{
					Finish(confirmed: false);
				}, true, _title, _currency, _unitCost, (IReadOnlyList<SavedItem>)null, (IReadOnlyList<int>)null, true, false, (SavedItem)(object)_item, (TakeItemTypes)0, (DisplayType)1);
			}
			finally
			{
				SuppressHijack = false;
			}
			((MonoBehaviour)this).StartCoroutine(RefreshAfterOpen());
			MerchantStackerPlugin.Log.LogInfo((object)$"Native qty open: {_title} max={_max} cost={_unitCost}");
		}

		private void BeginSession(string title, CollectableItem? item, int unitCost, CurrencyType currency, int maxQuantity, bool hijacked)
		{
			//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)
			_title = (string.IsNullOrEmpty(title) ? "Buy" : title);
			_item = item;
			_unitCost = Math.Max(1, unitCost);
			_currency = currency;
			_min = 1;
			_max = Math.Max(1, maxQuantity);
			_quantity = 1;
			_hijacked = hijacked;
			_inShop = false;
			_shopRoot = null;
			_shopStats = null;
			_active = true;
			ResetHoldState();
			InventoryPaneInput.IsInputBlocked = true;
		}

		private void BindShopCostText(ShopItemStats stats)
		{
			_boundCostText = null;
			_originalCostText = null;
			_boundStock = null;
			_originalShopTitle = null;
			try
			{
				object? obj = ItemCostTextField?.GetValue(stats);
				TextMeshPro val = (TextMeshPro)((obj is TextMeshPro) ? obj : null);
				if (val != null)
				{
					_boundCostText = val;
					_originalCostText = ((TMP_Text)val).text;
				}
				_boundStock = ((Component)stats).GetComponentInParent<ShopMenuStock>();
				if ((Object)(object)_boundStock != (Object)null)
				{
					_originalShopTitle = _boundStock.Title;
				}
			}
			catch
			{
			}
		}

		private void BuildConfirmQtyHud()
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_hudRoot != (Object)null || (Object)(object)_shopStats == (Object)null)
			{
				return;
			}
			ShopConfirmShowPatches.BuildingQtyHud = true;
			try
			{
				Transform root = ((Component)_shopStats).transform.root;
				Transform val = FindNamedTransform(root, "Item Confirm Group");
				Transform val2 = FindNamedTransform(root, "Confirm");
				if ((Object)(object)val2 == (Object)null)
				{
					MerchantStackerPlugin.Log.LogWarning((object)"Qty HUD: Confirm transform not found");
					return;
				}
				TextMeshPro val3 = FindTemplateTmp(val2) ?? _boundCostText;
				if ((Object)(object)val3 == (Object)null)
				{
					MerchantStackerPlugin.Log.LogWarning((object)"Qty HUD: no TMP template");
					return;
				}
				Transform val4 = (((Object)(object)val != (Object)null) ? val : val2);
				EnsureConfirmItemArtVisible();
				GetQtyRowLocal(val4, out _qtyLocal, out _arrowUpLocal, out _arrowDownLocal, out _currencyLocal, out _costLocal);
				_hudRoot = new GameObject("MerchantStacker_QtyHud");
				_hudRoot.layer = ((Component)val4).gameObject.layer;
				_hudRoot.transform.SetParent(val4, false);
				_hudRoot.transform.localPosition = Vector3.zero;
				_hudRoot.transform.localRotation = Quaternion.identity;
				_hudRoot.transform.localScale = Vector3.one;
				TextMeshPro val5 = FindConfirmCostTmp(val2) ?? val3;
				float num = Math.Max(5f, ((TMP_Text)val5).fontSize);
				_hudQty = CloneTmpLocal(val3, _hudRoot.transform, "Qty", _qtyLocal, "1", num * 2.7f, (TextAlignmentOptions)5);
				_hudCost = CloneTmpLocal(val5, _hudRoot.transform, "TotalCost", _costLocal, "0", num * 2f, (TextAlignmentOptions)4);
				object? obj = CostSpriteField?.GetValue(_shopStats);
				SpriteRenderer val6 = (SpriteRenderer)((obj is SpriteRenderer) ? obj : null);
				if ((Object)(object)val6 != (Object)null)
				{
					_hudCurrencyIcon = CloneSpriteLocal(val6, _hudRoot.transform, "CurrencyIcon", _currencyLocal, 2f);
					Sprite currencySprite = _shopStats.GetCurrencySprite();
					if ((Object)(object)currencySprite != (Object)null)
					{
						_hudCurrencyIcon.sprite = currencySprite;
					}
				}
				if (TryCreateVerticalArrowsLocal(val2, val4, _hudRoot.transform, _arrowUpLocal, _arrowDownLocal))
				{
					MerchantStackerPlugin.Log.LogInfo((object)"Qty HUD arrows: ok");
				}
				else
				{
					MerchantStackerPlugin.Log.LogWarning((object)"Qty HUD: no arrow templates found");
				}
				HideConfirmChrome(val2, val);
				HideNativeConfirmCosts(val2);
				CacheChromeToKeepOff(val2, val);
				_lastHudQty = int.MinValue;
				_lastHudTotal = int.MinValue;
				_lastArrowUpOn = _quantity >= _max;
				_lastArrowDownOn = _quantity <= _min;
				MatchArrowDrawOrderToQty();
				RefreshInShopHud();
				ReassertHudPoses();
				ForceArrowRenderersOn();
				MerchantStackerPlugin.Log.LogInfo((object)($"Qty HUD row qty={_qtyLocal} cost={_costLocal} arrows={(Object)(object)_hudArrowUp != (Object)null} " + $"arrowSize={MeshSize(_hudArrowUp)}"));
			}
			catch (Exception ex)
			{
				MerchantStackerPlugin.Log.LogWarning((object)("Qty HUD build failed: " + ex.Message));
				DestroyInShopHud(restoreTexts: true);
			}
			finally
			{
				ShopConfirmShowPatches.BuildingQtyHud = false;
			}
		}

		private void HideNativeConfirmCosts(Transform confirm)
		{
			_hiddenNativeCost.Clear();
			Transform[] componentsInChildren = ((Component)confirm).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string name = ((Object)val).name;
				if (!(name != "Costs") || !(name != "Money") || !(name != "Item cost") || !(name != "Geo Sprite"))
				{
					MeshRenderer[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<MeshRenderer>(true);
					for (int j = 0; j < componentsInChildren2.Length; j++)
					{
						((Renderer)componentsInChildren2[j]).enabled = false;
					}
					SpriteRenderer[] componentsInChildren3 = ((Component)val).GetComponentsInChildren<SpriteRenderer>(true);
					for (int j = 0; j < componentsInChildren3.Length; j++)
					{
						((Renderer)componentsInChildren3[j]).enabled = false;
					}
					if (((Component)val).gameObject.activeSelf)
					{
						((Component)val).gameObject.SetActive(false);
					}
					_hiddenNativeCost.Add(((Component)val).gameObject);
				}
			}
		}

		private static TextMeshPro? FindConfirmCostTmp(Transform confirm)
		{
			TextMeshPro[] componentsInChildren = ((Component)confirm).GetComponentsInChildren<TextMeshPro>(true);
			foreach (TextMeshPro val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name == "Item cost")
				{
					return val;
				}
			}
			return null;
		}

		private static void GetQtyRowLocal(Transform layoutParent, out Vector3 qtyLocal, out Vector3 upLocal, out Vector3 downLocal, out Vector3 currencyLocal, out Vector3 costLocal)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			Vector3 localPosition = default(Vector3);
			((Vector3)(ref localPosition))..ctor(-3.4f, 1.5f, -3f);
			foreach (Transform item in layoutParent)
			{
				Transform val = item;
				if ((Object)(object)val != (Object)null && ((Object)val).name == "Item Sprite")
				{
					localPosition = val.localPosition;
					break;
				}
			}
			float z = localPosition.z;
			float num = localPosition.y - 3.5f;
			float num2 = localPosition.x - 0.85f;
			qtyLocal = new Vector3(num2 - 0.9f, num, z);
			upLocal = new Vector3(qtyLocal.x, num + 1.1f, z);
			downLocal = new Vector3(qtyLocal.x, num - 1.1f, z);
			currencyLocal = new Vector3(num2 + 0.85f, num, z);
			costLocal = new Vector3(num2 + 1.55f, num, z);
		}

		private bool TryCreateVerticalArrowsLocal(Transform confirm, Transform layoutParent, Transform arrowParent, Vector3 upLocal, Vector3 downLocal)
		{
			//IL_0050: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			SpriteRenderer val = (SpriteRenderer)(((object)_hudCurrencyIcon) ?? ((object)/*isinst with value type is only supported in some contexts*/));
			EnsureArrowSpriteCached();
			if ((Object)(object)_cachedArrowSprite != (Object)null && (Object)(object)val != (Object)null)
			{
				_hudArrowUp = CloneSpriteCaret(val, arrowParent, "ArrowUp", upLocal, 90f, 2f);
				_hudArrowDown = CloneSpriteCaret(val, arrowParent, "ArrowDown", downLocal, 270f, 2f);
				ApplySprite(_hudArrowUp, _cachedArrowSprite);
				ApplySprite(_hudArrowDown, _cachedArrowSprite);
				RememberArrowBaseScales();
				MerchantStackerPlugin.Log.LogInfo((object)$"Arrows from sprite '{((Object)_cachedArrowSprite).name}' size={SpriteSize(_hudArrowUp)}");
				return true;
			}
			if ((Object)(object)val != (Object)null && (Object)(object)val.sprite != (Object)null)
			{
				_hudArrowUp = CloneSpriteCaret(val, arrowParent, "ArrowUp", upLocal, 90f, 2f);
				_hudArrowDown = CloneSpriteCaret(val, arrowParent, "ArrowDown", downLocal, 270f, 2f);
				RememberArrowBaseScales();
				MerchantStackerPlugin.Log.LogInfo((object)$"Arrows from currency sprite '{((Object)val.sprite).name}' size={SpriteSize(_hudArrowUp)}");
				return true;
			}
			EnsureCaretMeshCached(confirm, layoutParent);
			if ((Object)(object)_cachedCaretMesh != (Object)null && (Object)(object)_cachedCaretMaterial != (Object)null)
			{
				_hudArrowUp = CreateMeshCaret(arrowParent, "ArrowUp", upLocal, 90f, 0.9f);
				_hudArrowDown = CreateMeshCaret(arrowParent, "ArrowDown", downLocal, -90f, 0.9f);
				RememberArrowBaseScales();
				MerchantStackerPlugin.Log.LogInfo((object)$"Arrows from tk2d caret mesh size={MeshSize(_hudArrowUp)}");
				if ((Object)(object)_hudArrowUp != (Object)null)
				{
					return (Object)(object)_hudArrowDown != (Object)null;
				}
				return false;
			}
			return false;
		}

		private static void EnsureCaretMeshCached(Transform confirm, Transform layoutParent)
		{
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_cachedCaretMesh != (Object)null && (Object)(object)_cachedCaretMaterial != (Object)null)
			{
				return;
			}
			GameObject val = null;
			Transform val2 = FindNamedTransform(confirm, "Pointer L") ?? FindNamedTransform(layoutParent, "Pointer L");
			if ((Object)(object)val2 != (Object)null)
			{
				Transform parent = val2.parent;
				while ((Object)(object)parent != (Object)null && ((Object)parent).name != "Yes" && ((Object)parent).name != "Confirm")
				{
					parent = parent.parent;
				}
				if ((Object)(object)parent != (Object)null && ((Object)parent).name == "Yes" && !((Component)parent).gameObject.activeSelf)
				{
					((Component)parent).gameObject.SetActive(true);
				}
				((Component)val2).gameObject.SetActive(true);
				InvAnimateUpAndDown component = ((Component)val2).GetComponent<InvAnimateUpAndDown>();
				if (component != null)
				{
					component.Show();
				}
				val = ((Component)val2).gameObject;
			}
			if ((Object)(object)val == (Object)null)
			{
				ScrollView[] array = Resources.FindObjectsOfTypeAll<ScrollView>();
				foreach (ScrollView val3 in array)
				{
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					Scene scene = ((Component)val3).gameObject.scene;
					if (!((Scene)(ref scene)).IsValid())
					{
						continue;
					}
					object? obj = ScrollUpArrowField?.GetValue(val3);
					Component val4 = (Component)((obj is Component) ? obj : null);
					if (!((Object)(object)val4 == (Object)null))
					{
						val4.gameObject.SetActive(true);
						Component obj2 = ((val4 is InvAnimateUpAndDown) ? val4 : null);
						if (obj2 != null)
						{
							((InvAnimateUpAndDown)obj2).Show();
						}
						val = val4.gameObject;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			MeshFilter componentInChildren = val.GetComponentInChildren<MeshFilter>(true);
			MeshRenderer componentInChildren2 = val.GetComponentInChildren<MeshRenderer>(true);
			if ((Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren2 == (Object)null || (Object)(object)componentInChildren.sharedMesh == (Object)null || (Object)(object)((Renderer)componentInChildren2).sharedMaterial == (Object)null)
			{
				MerchantStackerPlugin.Log.LogWarning((object)$"Caret bake skipped: mesh={(Object)(object)((componentInChildren != null) ? componentInChildren.sharedMesh : null) != (Object)null} mat={(Object)(object)((componentInChildren2 != null) ? ((Renderer)componentInChildren2).sharedMaterial : null) != (Object)null}");
				return;
			}
			Bounds bounds = componentInChildren.sharedMesh.bounds;
			Vector3 size = ((Bounds)(ref bounds)).size;
			if (Mathf.Max(size.x, size.y) < 0.08f)
			{
				MerchantStackerPlugin.Log.LogInfo((object)$"Caret bake skipped: mesh too small ({size})");
				return;
			}
			_cachedCaretMesh = Object.Instantiate<Mesh>(componentInChildren.sharedMesh);
			((Object)_cachedCaretMesh).name = "MerchantStacker_CaretMesh";
			_cachedCaretMaterial = ((Renderer)componentInChildren2).sharedMaterial;
			_cachedCaretSortLayer = ((Renderer)componentInChildren2).sortingLayerID;
			_cachedCaretSortOrder = Math.Max(((Renderer)componentInChildren2).sortingOrder + 20, 260);
			ManualLogSource log = MerchantStackerPlugin.Log;
			string text = $"Cached tk2d caret mesh verts={_cachedCaretMesh.vertexCount} ";
			bounds = _cachedCaretMesh.bounds;
			log.LogInfo((object)(text + $"bounds={((Bounds)(ref bounds)).size}"));
		}

		private static void EnsureArrowSpriteCached()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			if (_arrowAssetsSearched)
			{
				return;
			}
			_arrowAssetsSearched = true;
			InventoryArrowContainer[] array = Resources.FindObjectsOfTypeAll<InventoryArrowContainer>();
			foreach (InventoryArrowContainer val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Scene scene = ((Component)val).gameObject.scene;
				if (!((Scene)(ref scene)).IsValid())
				{
					continue;
				}
				SpriteRenderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<SpriteRenderer>(true);
				foreach (SpriteRenderer val2 in componentsInChildren)
				{
					if ((Object)(object)((val2 != null) ? val2.sprite : null) != (Object)null && LooksLikeArrowSprite(((Object)val2.sprite).name, ((Object)((Component)val2).gameObject).name))
					{
						_cachedArrowSprite = val2.sprite;
						MerchantStackerPlugin.Log.LogInfo((object)("Cached arrow sprite from InventoryArrowContainer '" + ((Object)val2.sprite).name + "'"));
						return;
					}
				}
			}
			Sprite[] array2 = Resources.FindObjectsOfTypeAll<Sprite>();
			foreach (Sprite val3 in array2)
			{
				if ((Object)(object)val3 == (Object)null || !LooksLikeArrowSprite(((Object)val3).name, ((Object)val3).name))
				{
					continue;
				}
				Rect rect = val3.rect;
				if (!(((Rect)(ref rect)).width > 128f))
				{
					rect = val3.rect;
					if (!(((Rect)(ref rect)).height > 128f))
					{
						_cachedArrowSprite = val3;
						ManualLogSource log = MerchantStackerPlugin.Log;
						string name = ((Object)val3).name;
						rect = val3.rect;
						object arg = ((Rect)(ref rect)).width;
						rect = val3.rect;
						log.LogInfo((object)$"Cached arrow sprite '{name}' ({arg}x{((Rect)(ref rect)).height})");
						break;
					}
				}
			}
		}

		private static bool LooksLikeArrowSprite(string spriteName, string goName)
		{
			string haystack = spriteName + " " + goName;
			if (ContainsIgnore(haystack, "map") || ContainsIgnore(haystack, "quest") || ContainsIgnore(haystack, "pan") || ContainsIgnore(haystack, "compass") || ContainsIgnore(haystack, "marker"))
			{
				return false;
			}
			if (!ContainsIgnore(haystack, "arrow") && !ContainsIgnore(haystack, "caret") && !ContainsIgnore(haystack, "chevron"))
			{
				return ContainsIgnore(haystack, "pointer");
			}
			return true;
		}

		private static GameObject CreateMeshCaret(Transform parent, string name, Vector3 localPos, float rotationZ, float scale)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_002b: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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)
			GameObject val = new GameObject(name);
			val.layer = ((Component)parent).gameObject.layer;
			val.transform.SetParent(parent, false);
			val.transform.localPosition = localPos;
			val.transform.localRotation = Quaternion.Euler(0f, 0f, rotationZ);
			val.transform.localScale = Vector3.one * scale;
			val.AddComponent<MeshFilter>().sharedMesh = _cachedCaretMesh;
			MeshRenderer val2 = val.AddComponent<MeshRenderer>();
			((Renderer)val2).sharedMaterial = _cachedCaretMaterial;
			((Renderer)val2).sortingLayerID = _cachedCaretSortLayer;
			((Renderer)val2).sortingOrder = _cachedCaretSortOrder;
			((Renderer)val2).enabled = true;
			Bounds bounds = ((Renderer)val2).bounds;
			float x = ((Bounds)(ref bounds)).size.x;
			bounds = ((Renderer)val2).bounds;
			float num = Mathf.Max(x, ((Bounds)(ref bounds)).size.y);
			if (num > 0.0001f && num < 0.5f)
			{
				Transform transform = val.transform;
				transform.localScale *= 0.8f / num;
			}
			return val;
		}

		private static void ApplySprite(GameObject? go, Sprite sprite)
		{
			if (!((Object)(object)go == (Object)null))
			{
				SpriteRenderer component = go.GetComponent<SpriteRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					component.sprite = sprite;
					((Renderer)component).enabled = true;
				}
			}
		}

		private void RememberArrowBaseScales()
		{
			//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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_hudArrowUp != (Object)null)
			{
				_arrowUpBaseLocalScale = _hudArrowUp.transform.localScale;
				_arrowUpLocalRot = _hudArrowUp.transform.localRotation;
			}
			if ((Object)(object)_hudArrowDown != (Object)null)
			{
				_arrowDownBaseLocalScale = _hudArrowDown.transform.localScale;
				_arrowDownLocalRot = _hudArrowDown.transform.localRotation;
			}
		}

		private void DestroyArrowPair()
		{
			if ((Object)(object)_hudArrowUp != (Object)null)
			{
				Object.Destroy((Object)(object)_hudArrowUp);
				_hudArrowUp = null;
			}
			if ((Object)(object)_hudArrowDown != (Object)null)
			{
				Object.Destroy((Object)(object)_hudArrowDown);
				_hudArrowDown = null;
			}
		}

		private static Vector3 MeshSize(GameObject? go)
		{
			//IL_0009: 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_0021: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null)
			{
				return Vector3.zero;
			}
			MeshRenderer componentInChildren = go.GetComponentInChildren<MeshRenderer>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				Bounds bounds = ((Renderer)componentInChildren).bounds;
				return ((Bounds)(ref bounds)).size;
			}
			return SpriteSize(go);
		}

		private static Vector3 SpriteSize(GameObject? go)
		{
			//IL_0009: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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)
			if ((Object)(object)go == (Object)null)
			{
				return Vector3.zero;
			}
			SpriteRenderer componentInChildren = go.GetComponentInChildren<SpriteRenderer>(true);
			if (!((Object)(object)componentInChildren != (Object)null))
			{
				return Vector3.zero;
			}
			Bounds bounds = ((Renderer)componentInChildren).bounds;
			return ((Bounds)(ref bounds)).size;
		}

		private static GameObject CloneSpriteCaret(SpriteRenderer template, Transform parent, string name, Vector3 localPos, float rotationZ, float scaleMul)
		{
			//IL_0032: 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_005a: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, parent);
			((Object)val).name = name;
			val.layer = ((Component)parent).gameObject.layer;
			val.SetActive(true);
			val.transform.localPosition = localPos;
			val.transform.localRotation = Quaternion.Euler(0f, 0f, rotationZ);
			val.transform.localScale = Vector3.one * scaleMul;
			for (int num = val.transform.childCount - 1; num >= 0; num--)
			{
				Object.Destroy((Object)(object)((Component)val.transform.GetChild(num)).gameObject);
			}
			SpriteRenderer component = val.GetComponent<SpriteRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				((Renderer)component).enabled = true;
				Color color = component.color;
				color.a = 1f;
				component.color = color;
				((Renderer)component).sortingOrder = Math.Max(((Renderer)template).sortingOrder + 10, 260);
				((Renderer)component).sortingLayerID = ((Renderer)template).sortingLayerID;
			}
			return val;
		}

		private void MatchArrowDrawOrderToQty()
		{
			if ((Object)(object)_hudQty == (Object)null)
			{
				return;
			}
			MeshRenderer component = ((Component)_hudQty).GetComponent<MeshRenderer>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			GameObject[] array = (GameObject[])(object)new GameObject[2] { _hudArrowUp, _hudArrowDown };
			foreach (GameObject val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					MeshRenderer[] componentsInChildren = val.GetComponentsInChildren<MeshRenderer>(true);
					foreach (MeshRenderer obj in componentsInChildren)
					{
						((Renderer)obj).enabled = true;
						((Renderer)obj).sortingLayerID = ((Renderer)component).sortingLayerID;
						((Renderer)obj).sortingOrder = ((Renderer)component).sortingOrder + 5;
					}
					SpriteRenderer[] componentsInChildren2 = val.GetComponentsInChildren<SpriteRenderer>(true);
					foreach (SpriteRenderer obj2 in componentsInChildren2)
					{
						((Renderer)obj2).enabled = true;
						((Renderer)obj2).sortingLayerID = ((Renderer)component).sortingLayerID;
						((Renderer)obj2).sortingOrder = ((Renderer)component).sortingOrder + 5;
					}
				}
			}
		}

		private void ForceArrowRenderersOn()
		{
			GameObject[] array = (GameObject[])(object)new GameObject[2] { _hudArrowUp, _hudArrowDown };
			foreach (GameObject val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					if (!val.activeSelf)
					{
						val.SetActive(true);
					}
					MeshRenderer[] componentsInChildren = val.GetComponentsInChildren<MeshRenderer>(true);
					for (int j = 0; j < componentsInChildren.Length; j++)
					{
						((Renderer)componentsInChildren[j]).enabled = true;
					}
					SpriteRenderer[] componentsInChildren2 = val.GetComponentsInChildren<SpriteRenderer>(true);
					for (int j = 0; j < componentsInChildren2.Length; j++)
					{
						((Renderer)componentsInChildren2[j]).enabled = true;
					}
				}
			}
		}

		private void HideConfirmChrome(Transform confirm, Transform? confirmGroup)
		{
			object obj = (((Object)(object)confirmGroup != (Object)null) ? ((object)confirmGroup) : ((object)confirm));
			ShopConfirmListPatches.SuppressConfirmChromePublic((Transform)obj);
			Transform val = confirm.Find("UI List");
			if ((Object)(object)val != (Object)null)
			{
				_hiddenConfirmList = ((Component)val).gameObject;
				if (((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
			Transform val2 = FindNamedTransform(confirm, "Confirm msg");
			if ((Object)(object)val2 != (Object)null)
			{
				_hiddenConfirmMsg = ((Component)val2).gameObject;
				if (((Component)val2).gameObject.activeSelf)
				{
					((Component)val2).gameObject.SetActive(false);
				}
			}
			Transform[] componentsInChildren = ((Component)obj).GetComponentsInChildren<Transform>(true);
			foreach (Transform val3 in componentsInChildren)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					string name = ((Object)val3).name;
					if ((ContainsIgnore(name, "cursor") || ContainsIgnore(name, "selector")) && ((Component)val3).gameObject.activeSelf)
					{
						((Component)val3).gameObject.SetActive(false);
					}
				}
			}
		}

		private static bool ContainsIgnore(string haystack, string needle)
		{
			return haystack.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private IEnumerator EnsureHudSoon()
		{
			yield return null;
			if (_active && _inShop)
			{
				ReassertHudPoses();
				MatchArrowDrawOrderToQty();
				ForceArrowRenderersOn();
				RefreshInShopHud();
			}
		}

		private void RefreshInShopHud()
		{
			//IL_00da: 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)
			int num = _unitCost * _quantity;
			bool flag = _quantity != _lastHudQty;
			bool flag2 = num != _lastHudTotal;
			_lastHudQty = _quantity;
			_lastHudTotal = num;
			ApplyTmp(_hudQty, _quantity.ToString(CultureInfo.InvariantCulture), flag || flag2);
			ApplyTmp(_hudCost, num.ToString(CultureInfo.InvariantCulture), force: true);
			if ((Object)(object)_shopStats != (Object)null && (_hiddenNativeCost.Count > 0 || flag2))
			{
				KeepNativeConfirmCostsHidden();
			}
			bool flag3 = _quantity < _max;
			bool flag4 = _quantity > _min;
			if (flag3 != _lastArrowUpOn || flag)
			{
				_lastArrowUpOn = flag3;
				SetArrowVisible(_hudArrowUp, flag3, _arrowUpBaseLocalScale);
			}
			if (flag4 != _lastArrowDownOn || flag)
			{
				_lastArrowDownOn = flag4;
				SetArrowVisible(_hudArrowDown, flag4, _arrowDownBaseLocalScale);
			}
			if ((Object)(object)_hudCurrencyIcon != (Object)null)
			{
				((Renderer)_hudCurrencyIcon).enabled = true;
				if (!((Component)_hudCurrencyIcon).gameObject.activeSelf)
				{
					((Component)_hudCurrencyIcon).gameObject.SetActive(true);
				}
			}
		}

		private static void SetArrowVisible(GameObject? arrow, bool fullyVisible, Vector3 baseLocalScale)
		{
			//IL_0010: 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)
			if (!((Object)(object)arrow == (Object)null))
			{
				arrow.transform.localScale = baseLocalScale * (fullyVisible ? 1f : 0.55f);
				MeshRenderer[] componentsInChildren = arrow.GetComponentsInChildren<MeshRenderer>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Renderer)componentsInChildren[i]).enabled = true;
				}
				SpriteRenderer[] componentsInChildren2 = arrow.GetComponentsInChildren<SpriteRenderer>(true);
				for (int i = 0; i < componentsInChildren2.Length; i++)
				{
					((Renderer)componentsInChildren2[i]).enabled = true;
				}
			}
		}

		private void ReassertHudPoses()
		{
			//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_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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: 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)
			if ((Object)(object)_hudQty != (Object)null)
			{
				SetLocalPose(_hudQty.transform, _qtyLocal, Vector3.one);
			}
			if ((Object)(object)_hudCost != (Object)null)
			{
				SetLocalPose(_hudCost.transform, _costLocal, Vector3.one);
			}
			if ((Object)(object)_hudCurrencyIcon != (Object)null)
			{
				SetLocalPose(((Component)_hudCurrencyIcon).transform, _currencyLocal, ((Component)_hudCurrencyIcon).transform.localScale);
			}
			if ((Object)(object)_hudArrowUp != (Object)null)
			{
				float num = (_lastArrowUpOn ? 1f : 0.55f);
				_hudArrowUp.transform.localPosition = _arrowUpLocal;
				_hudArrowUp.transform.localRotation = _arrowUpLocalRot;
				_hudArrowUp.transform.localScale = _arrowUpBaseLocalScale * num;
			}
			if ((Object)(object)_hudArrowDown != (Object)null)
			{
				float num2 = (_lastArrowDownOn ? 1f : 0.55f);
				_hudArrowDown.transform.localPosition = _arrowDownLocal;
				_hudArrowDown.transform.localRotation = _arrowDownLocalRot;
				_hudArrowDown.transform.localScale = _arrowDownBaseLocalScale * num2;
			}
		}

		private static void ApplyTmp(TextMeshPro? tmp, string value, bool force = false)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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)
			if ((Object)(object)tmp == (Object)null)
			{
				return;
			}
			try
			{
				if (!((Component)tmp).gameObject.activeSelf)
				{
					((Component)tmp).gameObject.SetActive(true);
				}
				((Behaviour)tmp).enabled = true;
				Color color = ((Graphic)tmp).color;
				if (color.a < 0.9f)
				{
					color.a = 1f;
					((Graphic)tmp).color = color;
				}
				string text = ((TMP_Text)tmp).text ?? string.Empty;
				if (force || !string.Equals(text.Trim(), value, StringComparison.Ordinal))
				{
					((TMP_Text)tmp).text = value;
					((TMP_Text)tmp).SetText(value);
					((TMP_Text)tmp).ForceMeshUpdate(true);
				}
				MeshRenderer component = ((Component)tmp).GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					((Renderer)component).enabled = true;
				}
			}
			catch
			{
			}
		}

		private void KeepNativeConfirmCostsHidden()
		{
			for (int i = 0; i < _hiddenNativeCost.Count; i++)
			{
				GameObject val = _hiddenNativeCost[i];
				if ((Object)(object)val != (Object)null && val.activeSelf)
				{
					val.SetActive(false);
				}
			}
		}

		private static void SetTmpAlpha(TextMeshPro? tmp, float alpha)
		{
			//IL_000b: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)tmp == (Object)null))
			{
				Color color = ((Graphic)tmp).color;
				color.a = alpha;
				((Graphic)tmp).color = color;
			}
		}

		private static void SetLocalPose(Transform t, Vector3 localPos, Vector3 localScale)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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)
			t.localPosition = localPos;
			t.localRotation = Quaternion.identity;
			t.localScale = localScale;
			RectTransform val = (RectTransform)(object)((t is RectTransform) ? t : null);
			if (val != null)
			{
				val.anchoredPosition3D = localPos;
			}
		}

		private static TextMeshPro CloneTmpLocal(TextMeshPro template, Transform parent, string name, Vector3 localPos, string text, float fontSize, TextAlignmentOptions alignment = (TextAlignmentOptions)5)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject);
			((Object)val).name = name;
			val.transform.SetParent(parent, false);
			val.SetActive(true);
			SetLocalPose(val.transform, localPos, Vector3.one);
			for (int num = val.transform.childCount - 1; num >= 0; num--)
			{
				Object.Destroy((Object)(object)((Component)val.transform.GetChild(num)).gameObject);
			}
			TextMeshPro component = val.GetComponent<TextMeshPro>();
			((Behaviour)component).enabled = true;
			((TMP_Text)component).fontSize = fontSize;
			((TMP_Text)component).alignment = alignment;
			((TMP_Text)component).enableWordWrapping = false;
			Color color = ((Graphic)template).color;
			color.a = 1f;
			((Graphic)component).color = color;
			((TMP_Text)component).SetText(text);
			((TMP_Text)component).ForceMeshUpdate(true);
			MeshRenderer component2 = val.GetComponent<MeshRenderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				((Renderer)component2).enabled = true;
				((Renderer)component2).sortingOrder = Math.Max(((Renderer)component2).sortingOrder, 250);
			}
			return component;
		}

		private static SpriteRenderer CloneSpriteLocal(SpriteRenderer template, Transform parent, string name, Vector3 localPos, float scaleMul)
		{
			//IL_002c: 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_003a: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Object.Instantiate<GameObject>(((Component)template).gameObject);
			((Object)obj).name = name;
			obj.transform.SetParent(parent, false);
			obj.SetActive(true);
			SetLocalPose(obj.transform, localPos, ((Component)template).transform.localScale * scaleMul);
			SpriteRenderer component = obj.GetComponent<SpriteRenderer>();
			((Renderer)component).enabled = true;
			Color color = component.color;
			color.a = 1f;
			component.color = color;
			((Renderer)component).sortingOrder = Math.Max(((Renderer)component).sortingOrder, 250);
			return component;
		}

		private static Transform? FindNamedTransform(Transform root, string name)
		{
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name == name)
				{
					return val;
				}
			}
			return null;
		}

		private static TextMeshPro? FindTemplateTmp(Transform confirm)
		{
			TextMeshPro[] componentsInChildren = ((Component)confirm).GetComponentsInChildren<TextMeshPro>(true);
			foreach (TextMeshPro val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name == "Text" && (Object)(object)val.transform.parent != (Object)null && ((Object)val.transform.parent).name == "Yes")
				{
					return val;
				}
			}
			componentsInChildren = ((Component)confirm).GetComponentsInChildren<TextMeshPro>(true);
			foreach (TextMeshPro val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}

		private static void ForceHideConfirmChromeOnly(ShopItemStats? stats)
		{
			Transform val = null;
			try
			{
				if ((Object)(object)stats != (Object)null)
				{
					val = ((Component)stats).transform.root;
				}
			}
			catch
			{
				val = null;
			}
			if ((Object)(object)val == (Object)null)
			{
				ShopMenuStock[] array = Object.FindObjectsByType<ShopMenuStock>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				foreach (ShopMenuStock val2 in array)
				{
					if (ShopConfirmListPatches.IsLiveOpenShopStock(val2))
					{
						val = ((Component)val2).transform.root;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			ShopConfirmListPatches.RestoreConfirmChromePublic();
			ShopConfirmListPatches.ForceEnableConfirmYesNoPublic();
			Transform[] componentsInChildren = ((Component)val).GetComponentsInChildren<Transform>(true);
			foreach (Transform val3 in componentsInChildren)
			{
				if ((Object)(object)val3 == (Object)null || ((Object)val3).name != "Item Confirm Group")
				{
					continue;
				}
				Transform[] componentsInChildren2 = ((Component)val3).GetComponentsInChildren<Transform>(true);
				foreach (Transform val4 in componentsInChildren2)
				{
					if ((Object)(object)val4 == (Object)null)
					{
						continue;
					}
					string name = ((Object)val4).name;
					if (!(name == "UI List") || !((Object)(object)val4.parent != (Object)null) || !(((Object)val4.parent).name == "Confirm"))
					{
						switch (name)
						{
						case "Yes":
						case "No":
						case "Confirm msg":
						case "Costs":
							break;
						default:
							continue;
						}
					}
					if (!((Component)val4).gameObject.activeSelf)
					{
						((Component)val4).gameObject.SetActive(true);
					}
				}
				if (((Component)val3).gameObject.activeSelf)
				{
					((Component)val3).gameObject.SetActive(false);
				}
			}
		}

		private void DestroyInShopHud(bool restoreTexts, bool restoreConfirmChrome = true)
		{
			if (restoreTexts)
			{
				if ((Object)(object)_boundStock != (Object)null && _originalShopTitle != null)
				{
					_boundStock.Title = _originalShopTitle;
				}
				if ((Object)(object)_boundCostText != (Object)null && _originalCostText != null)
				{
					ApplyTmp(_boundCostText, _originalCostText);
				}
			}
			ClearTmpVisual(_hudQty);
			ClearTmpVisual(_hudCost);
			if ((Object)(object)_hudRoot != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)_hudRoot);
			}
			_hudRoot = null;
			_hudQty = null;
			_hudArrowUp = null;
			_hudArrowDown = null;
			_hudCost = null;
			_hudCurrencyIcon = null;
			_chromeToKeepOff.Clear();
			ShopConfirmShowPatches.LockConfirmChrome = false;
			_itemArtSprite = null;
			_itemArtName = null;
			_itemArtSpriteSr = null;
			_itemArtNameTmp = null;
			_itemArtNameMr = null;
			ScrubLeftoverQtyHud();
			if (restoreConfirmChrome)
			{
				if ((Object)(object)_hiddenConfirmList != (Object)null)
				{
					_hiddenConfirmList.SetActive(true);
					_hiddenConfirmList = null;
				}
				if ((Object)(object)_hiddenConfirmMsg != (Object)null)
				{
					_hiddenConfirmMsg.SetActive(true);
					_hiddenConfirmMsg = null;
				}
				foreach (GameObject item in _hiddenNativeCost)
				{
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					TextMeshPro[] componentsInChildren = item.GetComponentsInChildren<TextMeshPro>(true);
					foreach (TextMeshPro val in componentsInChildren)
					{
						if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name == "Item cost" && _unitCost > 0)
						{
							ApplyTmp(val, _unitCost.ToString(CultureInfo.InvariantCulture));
						}
					}
					item.SetActive(true);
				}
				_hiddenNativeCost.Clear();
			}
			else
			{
				_hiddenConfirmList = null;
				_hiddenConfirmMsg = null;
				_hiddenNativeCost.Clear();
			}
			if (restoreTexts)
			{
				_boundStock = null;
				_originalShopTitle = null;
				_boundCostText = null;
				_originalCostText = null;
			}
		}

		private static void ClearTmpVisual(TextMeshPro? tmp)
		{
			if ((Object)(object)tmp == (Object)null)
			{
				return;
			}
			try
			{
				((TMP_Text)tmp).SetText(string.Empty);
				((TMP_Text)tmp).ForceMeshUpdate(true);
				MeshRenderer component = ((Component)tmp).GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					((Renderer)component).enabled = false;
				}
			}
			catch
			{
			}
		}

		private static void ScrubLeftoverQtyHud()
		{
			//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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Invalid comparison between Unknown and I4
			GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
			foreach (GameObject val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				bool flag;
				try
				{
					Scene scene = val.scene;
					flag = ((Scene)(ref scene)).IsValid() || (int)((Object)val).hideFlags > 0;
				}
				catch
				{
					continue;
				}
				if ((flag || !(((Object)val).name != "MerchantStacker_QtyHud")) && (((Object)val).name == "MerchantStacker_QtyHud" || ((Object)val).name == "TotalCost" || ((Object)val).name == "Qty" || ((Object)val).name == "ArrowUp" || ((Object)val).name == "ArrowDown" || ((Object)val).name == "CurrencyIcon") && (((Object)val).name == "MerchantStacker_QtyHud" || ((Object)(object)val.transform.parent != (Object)null && (((Object)val.transform.parent).name == "MerchantStacker_QtyHud" || ((Object)val.transform.parent).name == "MerchantStacker_QuantityPicker" || (((Object)val).name == "MerchantStacker_QtyHud" && ((Object)val.transform.parent).name == "Item Confirm Group")))))
				{
					TextMeshPro[] componentsInChildren = val.GetComponentsInChildren<TextMeshPro>(true);
					for (int j = 0; j < componentsInChildren.Length; j++)
					{
						ClearTmpVisual(componentsInChildren[j]);
					}
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private void ClearPickerHudChildren()
		{
			for (int num = ((Component)this).transform.childCount - 1; num >= 0; num--)
			{
				Transform child = ((Component)this).transform.GetChild(num);
				if (!((Object)(object)child == (Object)null))
				{
					TextMeshPro[] componentsInChildren = ((Component)child).GetComponentsInChildren<TextMeshPro>(true);
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						ClearTmpVisual(componentsInChildren[i]);
					}
					Object.DestroyImmediate((Object)(object)((Component)child).gameObject);
				}
			}
			_hudRoot = null;
			_hudQty = null;
			_hudArrowUp = null;
			_hudArrowDown = null;
			_hudCost = null;
			_hudCurrencyIcon = null;
		}

		private IEnumerator RefreshAfterOpen()
		{
			yield return null;
			yield return null;
			if (_active && !_inShop)
			{
				RefreshNativeDisplay();
			}
		}

		private static void CompleteInShopPurchase(ShopItemStats shopStats, int qty, Action? purchaseDone)
		{
			ShopMenuStock stock = ((Component)shopStats).GetComponentInParent<ShopMenuStock>();
			PurchaseBatcher.ClearPendingQuantity();
			PurchaseBatcher.ExpectingFsmPurchase = false;
			PurchaseBatcher.BuyShopItem(shopStats, qty, 0, delegate
			{
				ShopMenuStock obj = stock;
				if (obj != null)
				{
					obj.SetWasItemPurchased(true);
				}
				ShowPurchaseFeedback(shopStats);
				ScrubLeftoverQtyHud();
				ForceHideConfirmChromeOnly(shopStats);
				purchaseDone?.Invoke();
				EventRegister.SendEvent(EventRegisterEvents.ResetShopWindow, (GameObject)null);
				PurchaseBatcher.EndShopPurchaseBlock();
				ShopConfirmListPatches.ClearPendingQtyOpen();
				GameCameras instance = GameCameras.instance;
				if (instance != null)
				{
					instance.HUDIn();
				}
				MerchantStackerPlugin.Log.LogInfo((object)"Bulk buy done → popup + ResetShopWindow");
			});
		}

		internal static void ShowPurchaseFeedback(ShopItemStats? stats)
		{
			try
			{
				object obj;
				if (stats == null)
				{
					obj = null;
				}
				else
				{
					ShopItem item = stats.Item;
					obj = ((item != null) ? item.Item : null);
				}
				CollectableItem val = (CollectableItem)((obj is CollectableItem) ? obj : null);
				if (val != null)
				{
					CollectableUIMsg.Spawn((ICollectableUIMsgItem)(object)val, (CollectableUIMsg)null, false);
					CollectableItemHeroReaction.DoReaction();
				}
			}
			catch (Exception ex)
			{
				MerchantStackerPlugin.Log.LogWarning((object)("ShowPurchaseFeedback: " + ex.Message));
			}
		}

		private void Finish(bool confirmed)
		{
			if (!_active)
			{
				return;
			}
			int num = Math.Max(1, _quantity);
			bool hijacked = _hijacked;
			bool inShop = _inShop;
			Action originalYes = _originalYes;
			Action originalNo = _originalNo;
			Action<int> onConfirm = _onConfirm;
			Action onCancel = _onCancel;
			ShopItemStats shopStats = _shopStats;
			Action purchaseDone = _purchaseDone;
			Action shopCancel = _shopCancel;
			_active = false;
			_hijacked = false;
			_inShop = false;
			_shopRoot = null;
			_shopStats = null;
			_originalYes = null;
			_originalNo = null;
			_onConfirm = null;
			_onCancel = null;
			_purchaseDone = null;
			_shopCancel = null;
			_item = null;
			DestroyInShopHud(restoreTexts: true, !confirmed);
			ForceHideConfirmChromeOnly(shopStats);
			ClearPickerHudChildren();
			ResetHoldState();
			InventoryPaneInput.IsInputBlocked = false;
			ShopConfirmListPatches.ClearPendingQtyOpen();
			if (confirmed)
			{
				PurchaseBatcher.PendingQuantity = num;
				MerchantStackerPlugin.Log.LogInfo((object)$"Qty confirmed: {num}");
			}
			else
			{
				PurchaseBatcher.ClearPendingQuantity();
				PurchaseBatcher.ExpectingFsmPurchase = false;
				PurchaseBatcher.EndShopPurchaseBlock();
			}
			if (inShop)
			{
				if (confirmed && (Object)(object)shopStats != (Object)null)
				{
					CompleteInShopPurchase(shopStats, num, purchaseDone);
					return;
				}
				ScrubLeftoverQtyHud();
				ClearPickerHudChildren();
				ForceHideConfirmChromeOnly(shopStats);
				ShopSelectionCache.Clear();
				ShopConfirmListPatches.BeginUiConfirmGrace();
				shopCancel?.Invoke();
				ScrubLeftoverQtyHud();
				ClearPickerHudChildren();
				MerchantStackerPlugin.Log.LogInfo((object)"Qty cancelled → ResetShopWindow");
			}
			else if (hijacked)
			{
				object? value = InstanceField.GetValue(null);
				YesNoBox val = (YesNoBox)((value is YesNoBox) ? value : null);
				if ((Object)(object)val != (Object)null)
				{
					CurrentYesField.SetValue(val, originalYes);
					CurrentNoField.SetValue(val, originalNo);
					SelectedStateField.SetValue(val, confirmed);
					DoEndMethod.Invoke(val, null);
				}
				else if (confirmed)
				{
					originalYes?.Invoke();
				}
				else
				{
					originalNo?.Invoke();
				}
			}
			else
			{
				ClearBoxHandlersAndClose();
				if (confirmed)
				{
					onConfirm?.Invoke(num);
				}
				else
				{
					onCancel?.Invoke();
				}
			}
		}

		private static void ClearBoxHandlersAndClose()
		{
			object? value = InstanceField.GetValue(null);
			DialogueYesNoBox val = (DialogueYesNoBox)((value is DialogueYesNoBox) ? value : null);
			if ((Object)(object)val != (Object)null)
			{
				CurrentYesField.SetValue(val, null);
				CurrentNoField.SetValue(val, null);
			}
			try
			{
				DialogueYesNoBox.ForceClose();
			}
			catch
			{
			}
		}

		private void ResetHoldState()
		{
			_upTimer = 0f;
			_downTimer = 0f;
			_upHeld = false;
			_downHeld = false;
			_upInterval = MerchantStackerPlugin.HoldInitialDelay.Value;
			_downInterval = MerchantStackerPlugin.HoldInitialDelay.Value;
			_heldStep = MerchantStackerPlugin.DpadStep.Value;
		}

		private void Update()
		{
			//IL_0042: 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_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Invalid comparison between Unknown and I4
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Invalid comparison between Unknown and I4
			ShopConfirmListPatches.PumpBlankConfirmWatchdog();
			if (!_active)
			{
				return;
			}
			_maxRecalcTimer -= Time.unscaledDeltaTime;
			if (_maxRecalcTimer <= 0f)
			{
				_maxRecalcTimer = 0.25f;
				int affordableCount = Eligibility.GetAffordableCount(_unitCost, _currency);
				int val = (((Object)(object)_item != (Object)null) ? Eligibility.GetRoomUntilCap(_item) : _max);
				int num = Math.Max(1, Math.Min(Math.Max(1, affordableCount), Math.Max(1, val)));
				if (num != _max)
				{
					_max = num;
					if (_quantity > _max)
					{
						_quantity = _max;
					}
					if (_inShop)
					{
						_lastHudQty = int.MinValue;
						RefreshInShopHud();
					}
					else
					{
						RefreshDisplay();
					}
				}
			}
			InputHandler instance = ManagerSingleton<InputHandler>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			HeroActions inputActions = instance.inputActions;
			MenuActions menuAction = Platform.Current.GetMenuAction(inputActions, false, false);
			if ((int)menuAction != 1)
			{
				if ((int)menuAction == 2)
				{
					Finish(confirmed: false);
					return;
				}
				int value = MerchantStackerPlugin.DpadStep.Value;
				int value2 = MerchantStackerPlugin.StickStep.Value;
				bool num2 = ((OneAxisInputControl)inputActions.Up).WasPressed || ((OneAxisInputControl)inputActions.RsUp).WasPressed;
				bool flag = ((OneAxisInputControl)inputActions.Down).WasPressed || ((OneAxisInputControl)inputActions.RsDown).WasPressed;
				bool upHeld = ((OneAxisInputControl)inputActions.Up).IsPressed || ((OneAxisInputControl)inputActions.RsUp).IsPressed;
				bool downHeld = ((OneAxisInputControl)inputActions.Down).IsPressed || ((OneAxisInputControl)inputActions.RsDown).IsPressed;
				int num3 = ((((OneAxisInputControl)inputActions.RsUp).WasPressed || ((OneAxisInputControl)inputActions.RsDown).WasPressed) ? value2 : value);
				int step = ((((OneAxisInputControl)inputActions.RsUp).IsPressed || ((OneAxisInputControl)inputActions.RsDown).IsPressed) ? value2 : value);
				if (num2)
				{
					Adjust(num3);
					BeginHold(up: true, step);
				}
				else if (flag)
				{
					Adjust(-num3);
					BeginHold(up: false, step);
				}
				else
				{
					TickHold(upHeld, downHeld, step);
				}
			}
			else
			{
				Finish(confirmed: true);
			}
		}

		private void BeginHold(bool up, int step)
		{
			_heldStep = step;
			float value = MerchantStackerPlugin.HoldInitialDelay.Value;
			if (up)
			{
				_upHeld = true;
				_downHeld = false;
				_upTimer = value;
				_upInterval = value;
			}
			else
			{
				_downHeld = true;
				_upHeld = false;
				_downTimer = value;
				_downInterval = value;
			}
		}

		private void TickHold(bool upHeld, bool downHeld, int step)
		{
			_heldStep = step;
			float value = MerchantStackerPlugin.HoldMinRepeat.Value;
			float value2 = MerchantStackerPlugin.HoldAccel.Value;
			float unscaledDeltaTime = Time.unscaledDeltaTime;
			if (upHeld && _upHeld)
			{
				_upTimer -= unscaledDeltaTime;
				if (_upTimer <= 0f)
				{
					Adjust(_heldStep);
					_upInterval = Math.Max(value, _upInterval * value2);
					_upTimer = _upInterval;
				}
			}
			else
			{
				_upHeld = false;
				_upInterval = MerchantStackerPlugin.HoldInitialDelay.Value;
			}
			if (downHeld && _downHeld)
			{
				_downTimer -= unscaledDeltaTime;
				if (_downTimer <= 0f)
				{
					Adjust(-_heldStep);
					_downInterval = Math.Max(value, _downInterval * value2);
					_downTimer = _downInterval;
				}
			}
			else
			{
				_downHeld = false;
				_downInterval = MerchantStackerPlugin.HoldInitialDelay.Value;
			}
		}

		private void Adjust(int delta)
		{
			int num = Math.Clamp(_quantity + delta, _min, _max);
			if (num != _quantity)
			{
				_quantity = num;
				PurchaseBatcher.PendingQuantity = _quantity;
				RefreshDisplay();
				MerchantStackerPlugin.Log.LogInfo((object)$"Qty -> {_quantity}");
			}
		}

		private void RefreshDisplay()
		{
			if (_inShop)
			{
				RefreshInShopHud();
			}
			else
			{
				RefreshNativeDisplay();
			}
		}

		private void RefreshNativeDisplay()
		{
			object? value = InstanceField.GetValue(null);
			DialogueYesNoBox val = (DialogueYesNoBox)((value is DialogueYesNoBox) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			int num = _unitCost * _quantity;
			RequiredCurrencyAmountField.SetValue(val, num);
			object? value2 = CurrencyTextField.GetValue(val);
			TMP_Text val2 = (TMP_Text)((value2 is TMP_Text) ? value2 : null);
			if (val2 != null)
			{
				val2.text = num.ToString(CultureInfo.InvariantCulture);
			}
			if ((Object)(object)_item == (Object)null)
			{
				return;
			}
			WillGetItemField.SetValue(val, _item);
			EnsureWillGetDisplay(val, _item);
			if (!(InstantiatedItemsField.GetValue(val) is List<SavedItemDisplay> list))
			{
				return;
			}
			foreach (SavedItemDisplay item in list)
			{
				if (!((Object)(object)item == (Object)null) && ((Component)item).gameObject.activeSelf)
				{
					item.Setup((SavedItem)(object)_item, _quantity);
					ForceAmountText(item, _quantity);
					break;
				}
			}
		}

		private static void EnsureWillGetDisplay(DialogueYesNoBox box, CollectableItem? item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return;
			}
			try
			{
				if (!(InstantiatedItemsField.GetValue(box) is List<SavedItemDisplay> list))
				{
					return;
				}
				object? value = ItemTemplateField.GetValue(box);
				SavedItemDisplay val = (SavedItemDisplay)((value is SavedItemDisplay) ? value : null);
				if (val != null)
				{
					while (list.Count < 1)
					{
						list.Add(Object.Instantiate<SavedItemDisplay>(val, ((Component)val).transform.parent));
					}
					((Component)list[0]).gameObject.SetActive(true);
					list[0].Setup((SavedItem)(object)item, 1);
					object? value2 = ItemsLayoutField.GetValue(box);
					Behaviour val2 = (Behaviour)((value2 is Behaviour) ? value2 : null);
					if (val2 != null)
					{
						((Component)val2).gameObject.SetActive(true);
					}
				}
			}
			catch
			{
			}
		}

		private static void ForceAmountText(SavedItemDisplay display, int qty)
		{
			try
			{
				object? obj = AccessTools.Field(typeof(SavedItemDisplay), "amountText")?.GetValue(display);
				TMP_Text val = (TMP_Text)((obj is TMP_Text) ? obj : null);
				if (val != null)
				{
					((Component)val).gameObject.SetActive(true);
					val.text = qty.ToString(CultureInfo.InvariantCulture);
				}
			}
			catch
			{
			}
		}
	}
	internal static class ShopSelectionCache
	{
		private static readonly string[] ItemObjectVarNames = new string[3] { "Shop Item", "Item", "Selected Item" };

		private static readonly string[] ItemIndexVarNames = new string[3] { "Current Item", "Item Number", "Selected Index" };

		internal static ShopItemStats? Stats { get; private set; }

		internal static ShopItem? Item
		{
			get
			{
				if (!((Object)(object)Stats != (Object)null))
				{
					return null;
				}
				return Stats.Item;
			}
		}

		internal static void Remember(ShopItemStats? stats)
		{
			if (!((Object)(object)stats == (Object)null) && !((Object)(object)stats.Item == (Object)null))
			{
				Stats = stats;
			}
		}

		internal static void Clear()
		{
			Stats = null;
		}

		internal static ShopItemStats? ResolveStats()
		{
			ShopItemStats? stats = Stats;
			if ((Object)(object)((stats != null) ? stats.Item : null) != (Object)null)
			{
				return Stats;
			}
			if (TryResolveFromFsm(out ShopItemStats stats2))
			{
				Remember(stats2);
				return stats2;
			}
			InventoryItemManager[] array = Object.FindObjectsByType<InventoryItemManager>((FindObjectsSortMode)0);
			foreach (InventoryItemManager val in array)
			{
				if (!((Object)(object)((val != null) ? val.CurrentSelected : null) == (Object)null))
				{
					ShopItemStats statsFromGameObject = GetStatsFromGameObject(((Component)val.CurrentSelected).gameObject);
					if ((Object)(object)((statsFromGameObject != null) ? statsFromGameObject.Item : null) != (Object)null)
					{
						Remember(statsFromGameObject);
						return statsFromGameObject;
					}
				}
			}
			return null;
		}

		private static bool TryResolveFromFsm(out ShopItemStats? stats)
		{
			stats = null;
			PlayMakerFSM[] array = Object.FindObjectsByType<PlayMakerFSM>((FindObjectsSortMode)0);
			foreach (PlayMakerFSM val in array)
			{
				if ((Object)(object)val == (Object)null || !((Behaviour)val).isActiveAndEnabled || val.FsmVariables == null)
				{
					continue;
				}
				string[] itemObjectVarNames = ItemObjectVarNames;
				foreach (string text in itemObjectVarNames)
				{
					FsmGameObject val2 = val.FsmVariables.FindFsmGameObject(text);
					if (!((Object)(object)((val2 != null) ? val2.Value : null) == (Object)null))
					{
						stats = GetStatsFromGameObject(val2.Value);
						ShopItemStats? obj = stats;
						if ((Object)(object)((obj != null) ? obj.Item : null) != (Object)null)
						{
							MerchantStackerPlugin.Log.LogDebug((object)("Shop item from FSM '" + text + "': " + stats.Item.DisplayName));
							return true;
						}
					}
				}
				itemObjectVarNames = ItemIndexVarNames;
				foreach (string text2 in itemObjectVarNames)
				{
					FsmInt val3 = val.FsmVariables.FindFsmInt(text2);
					if (val3 == null)
					{
						continue;
					}
					ShopMenuStock val4 = ((Component)val).GetComponent<ShopMenuStock>() ?? ((Component)val).GetComponentInParent<ShopMenuStock>() ?? ((Component)val).GetComponentInChildren<ShopMenuStock>(true);
					if ((Object)(object)val4 == (Object)null)
					{
						continue;
					}
					int value = val3.Value;
					if (value >= 0 && value < val4.GetItemCount())
					{
						stats = GetStatsFromGameObject(val4.GetItemGameObject(value));
						ShopItemStats? obj2 = stats;
						if ((Object)(object)((obj2 != null) ? obj2.Item : null) != (Object)null)
						{
							MerchantStackerPlugin.Log.LogDebug((object)$"Shop item from FSM '{text2}'={value}: {stats.Item.DisplayName}");
							return true;
						}
					}
				}
			}
			stats = null;
			return false;
		}

		internal static ShopItemStats? GetStatsFromGameObject(GameObject? go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return null;
			}
			return go.GetComponent<ShopItemStats>() ?? go.GetComponentInChildren<ShopItemStats>(true) ?? go.GetComponentInParent<ShopItemStats>();
		}
	}
	[HarmonyPatch]
	internal static class ShopSelectionCachePatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryItemSelectable), "Select")]
		private static void SelectPostfix(InventoryItemSelectable __instance)
		{
			ShopSelectionCache.Remember(ShopSelectionCache.GetStatsFromGameObject((__instance != null) ? ((Component)__instance).gameObject : null));
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryItemManager), "SetSelected", new Type[]
		{
			typeof(GameObject),
			typeof(bool)
		})]
		private static void SetSelectedGoPostfix(GameObject selectedGameObject)
		{
			ShopSelectionCache.Remember(ShopSelectionCache.GetStatsFromGameObject(selectedGameObject));
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryItemManager), "SetSelected", new Type[]
		{
			typeof(InventoryItemSelectable),
			typeof(SelectionDirection?),
			typeof(bool)
		})]
		private static void SetSelectedSelectablePostfix(InventoryItemSelectable selectable)
		{
			ShopSelectionCache.Remember(ShopSelectionCache.GetStatsFromGameObject((selectable != null) ? ((Component)selectable).gameObject : null));
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(SetShopItemPurchased), "OnEnter")]
		private static void CachePurchaseTargetV1(SetShopItemPurchased __instance)
		{
			ShopSelectionCache.Remember(ShopSelectionCache.GetStatsFromGameObject(FSMUtility.GetSafe(__instance.Target, (FsmStateAction)(object)__instance)));
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(SetShopItemPurchasedV2), "OnEnter")]
		private static void CachePurchaseTargetV2(SetShopItemPurchasedV2 __instance)
		{
			ShopSelectionCache.Remember(ShopSelectionCache.GetStatsFromGameObject(FSMUtility.GetSafe(__instance.Target, (FsmStateAction)(object)__instance)));
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ShopMenuStock), "GetItemGameObject")]
		private static void GetItemGameObjectPostfix(ShopMenuStock __instance, int itemNum, GameObject __result)
		{
			ShopSelectionCache.Remember(ShopSelectionCache.GetStatsFromGameObject(__result));
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ShopMenuStock), "GetCost")]
		private static void GetCostPostfix(ShopMenuStock __instance, int itemNum)
		{
			try
			{
				ShopSelectionCache.Remember(ShopSelectionCache.GetStatsFromGameObject(__instance.GetItemGameObject(itemNum)));
			}
			catch
			{
			}
		}
	}
}
namespace MerchantStacker.Patches
{
	[HarmonyPatch]
	internal static class ConfirmDialogPatches
	{
		private static readonly FieldInfo CurrentYesField = AccessTools.Field(typeof(YesNoBox), "currentYes");

		private static readonly FieldInfo CurrentNoField = AccessTools.Field(typeof(YesNoBox), "currentNo");

		private static readonly FieldInfo RequiredCurrencyAmountField = AccessTools.Field(typeof(DialogueYesNoBox), "requiredCurrencyAmount");

		private static readonly FieldInfo WillGetItemField = AccessTools.Field(typeof(DialogueYesNoBox), "willGetItem");

		[HarmonyPostfix]
		[HarmonyPatch(typeof(YesNoBox), "InternalOpen")]
		private static void InternalOpenPostfix(YesNoBox __instance)
		{
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!MerchantStackerPlugin.Enabled.Value || PurchaseBatcher.IsBatching || QuantityPicker.SuppressHijack || (Object)(object)QuantityPicker.Instance == (Object)null || QuantityPicker.Instance.IsOpen)
				{
					return;
				}
				DialogueYesNoBox val = (DialogueYesNoBox)(object)((__instance is DialogueYesNoBox) ? __instance : null);
				if (val == null || IsMerchantShopOpen())
				{
					return;
				}
				int valueOrDefault = (RequiredCurrencyAmountField?.GetValue(val) as int?).GetValueOrDefault();
				if (valueOrDefault <= 0)
				{
					return;
				}
				ShopItemStats val2 = ShopSelectionCache.ResolveStats();
				if (!((Object)(object)((val2 != null) ? val2.Item : null) == (Object)null) && Eligibility.ShouldOfferBulkQty(val2.Item))
				{
					object? obj = WillGetItemField?.GetValue(val);
					CollectableItem val3 = (CollectableItem)(((obj is CollectableItem) ? obj : null) ?? ((object)/*isinst with value type is only supported in some contexts*/));
					if (!((Object)(object)val3 == (Object)null))
					{
						QuantityPicker.Instance.Hijack(val, val2.Item.DisplayName, val3, (val2.Item.Cost > 0) ? val2.Item.Cost : valueOrDefault, val2.Item.CurrencyType, Eligibility.GetMaxQuantity(val2.Item), CurrentYesField?.GetValue(val) as Action, CurrentNoField?.GetValue(val) as Action);
					}
				}
			}
			catch (Exception arg)
			{
				MerchantStackerPlugin.Log.LogError((object)$"ConfirmDialogPatches: {arg}");
			}
		}

		private static bool IsMerchantShopOpen()
		{
			try
			{
				ShopMenuStock[] array = Object.FindObjectsByType<ShopMenuStock>((FindObjectsSortMode)0);
				foreach (ShopMenuStock val in array)
				{
					if ((Object)(object)val != (Object)null && ((Behaviour)val).isActiveAndEnabled)
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(InventoryPaneInput), "Update")]
	internal static class InventoryPaneInputPatches
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			if (!((Object)(object)QuantityPicker.Instance == (Object)null))
			{
				return !QuantityPicker.Instance.IsOpen;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class MachinePurchasePatches
	{
		private static int _pendingCollectQty;

		private static bool _skipNextCollect;

		private static bool _waitingForConfirm;

		private static CollectableItem? _pendingItem;

		private static TakeCurrency? _heldTakeAction;

		private static int _heldUnitCost;

		private static CurrencyType _heldCurrency;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TakeCurrency), "OnEnter")]
		private static bool TakeCurrencyPrefix(TakeCurrency __instance)
		{
			//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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			if (!MerchantStackerPlugin.Enabled.Value || PurchaseBatcher.IsBatching || _waitingForConfirm)
			{
				return true;
			}
			if (((NamedVariable)__instance.CurrencyType).IsNone || __instance.Amount.Value <= 0)
			{
				return true;
			}
			int num = PurchaseBatcher.ConsumePendingQuantity();
			if (num > 1 && IsRosaryStringMachine((FsmStateAction)(object)__instance))
			{
				CurrencyType val = (CurrencyType)(object)__instance.CurrencyType.Value;
				CurrencyManager.TakeCurrency(__instance.Amount.Value * num, val, true);
				_pendingCollectQty = num;
				_skipNextCollect = false;
				((FsmStateAction)__instance).Finish();
				return false;
			}
			if (num == 1)
			{
				return true;
			}
			if (!IsRosaryStringMachine((FsmStateAction)(object)__instance))
			{
				return true;
			}
			CurrencyType val2 = (CurrencyType)(object)__instance.CurrencyType.Value;
			int value = __instance.Amount.Value;
			CollectableItem val3 = FindMachineCollectable((FsmStateAction)(object)__instance);
			int val4 = (((Object)(object)val3 != (Object)null) ? Eligibility.GetRoomUntilCap(val3) : 20);
			int affordableCount = Eligibility.GetAffordableCount(value, val2);
			int num2 = Math.Max(1, Math.Min(val4, affordableCount));
			if (num2 <= 1 || (Object)(object)val3 == (Object)null)
			{
				return true;
			}
			if ((Object)(object)QuantityPicker.Instance == (Object)null)
			{
				return true;
			}
			_waitingForConfirm = true;
			_heldTakeAction = __instance;
			_heldUnitCost = value;
			_heldCurrency = val2;
			_pendingItem = val3;
			QuantityPicker.Instance.Open(((SavedItem)val3).GetPopupName(), val3, value, val2, num2, delegate(int qty)
			{
				//IL_001d: Unknown result ty