Decompiled source of RoundsTheGathering v2.0.0

DeckBuilder.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using DeckBuilder.CardDelete;
using DeckBuilder.Cards;
using DeckBuilder.Data;
using DeckBuilder.GameIntegration;
using DeckBuilder.Networking;
using DeckBuilder.UI;
using HarmonyLib;
using InfoOverhaul.Delta;
using Microsoft.CodeAnalysis;
using ModdingUtils.Utils;
using Photon.Pun;
using RarityLib.Utils;
using TMPro;
using UnboundLib;
using UnboundLib.Cards;
using UnboundLib.GameModes;
using UnboundLib.Networking;
using UnboundLib.Utils;
using UnboundLib.Utils.UI;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: AssemblyCompany("DeckBuilder")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+146ac727a7fc6b83f382d57f53cce40478349c58")]
[assembly: AssemblyProduct("DeckBuilder Mod for ROUNDS")]
[assembly: AssemblyTitle("DeckBuilder")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 DeckBuilder
{
	public static class CardPrerequisiteRegistry
	{
		private static readonly Dictionary<string, string> _prerequisites = new Dictionary<string, string>();

		public static int Count => _prerequisites.Count;

		public static void RegisterPrerequisite(string cardName, string requiredCardName)
		{
			if (!string.IsNullOrEmpty(cardName) && !string.IsNullOrEmpty(requiredCardName))
			{
				_prerequisites[cardName] = requiredCardName;
			}
		}

		public static bool HasPrerequisite(string cardName)
		{
			if (!string.IsNullOrEmpty(cardName))
			{
				return _prerequisites.ContainsKey(cardName);
			}
			return false;
		}

		public static string GetPrerequisite(string cardName)
		{
			if (string.IsNullOrEmpty(cardName) || !_prerequisites.TryGetValue(cardName, out var value))
			{
				return null;
			}
			return value;
		}

		public static bool IsUnlocked(string cardName, ICollection<string> ownedCardNames)
		{
			string prerequisite = GetPrerequisite(cardName);
			if (string.IsNullOrEmpty(prerequisite))
			{
				return true;
			}
			return ownedCardNames?.Contains(prerequisite) ?? false;
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("DeckBuilder", "DeckBuilder Mod for ROUNDS", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		internal static string PluginDirectory { get; private set; }

		private void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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)
			Logger = ((BaseUnityPlugin)this).Logger;
			PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? "";
			RTGLog.Section("Plugin Awake");
			new Harmony("DeckBuilder").PatchAll();
			((Component)this).gameObject.AddComponent<DeckManager>();
			((Component)this).gameObject.AddComponent<CardDeleteManager>();
			((Component)this).gameObject.AddComponent<DeckHUDOverlay>();
			GameObject val = new GameObject("RTG_UIRoot");
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<DeckSelectorScreen>();
			val.AddComponent<CreateDeckScreen>();
			val.AddComponent<DeckEditorScreen>();
			val.AddComponent<DeckBuilderUiInputLock>();
			val.AddComponent<CardBarSelectorUI>();
			RTGLog.Line("Plugin DeckBuilder loaded.");
		}

		private void Start()
		{
			DeckBuilderCardRegistrar.RegisterAll();
		}
	}
	internal static class RTGLog
	{
		private const string Sep = "=====================";

		public static void Section(string title)
		{
			Plugin.Logger.LogInfo((object)"=====================");
			Plugin.Logger.LogInfo((object)("[DeckBuilder] " + title));
			Plugin.Logger.LogInfo((object)"=====================");
		}

		public static void Line(string message)
		{
			Plugin.Logger.LogInfo((object)("[DeckBuilder] " + message));
		}

		public static void Warn(string message)
		{
			Plugin.Logger.LogWarning((object)("[DeckBuilder] " + message));
		}

		public static void Error(string message)
		{
			Plugin.Logger.LogError((object)("[DeckBuilder] " + message));
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "DeckBuilder";

		public const string PLUGIN_NAME = "DeckBuilder Mod for ROUNDS";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace DeckBuilder.UI
{
	public class CreateDeckScreen : MonoBehaviour
	{
		public static CreateDeckScreen instance;

		private Canvas _canvas;

		private TMP_InputField _nameField;

		private TMP_InputField _maxSizeField;

		private Button _createBtn;

		private TextMeshProUGUI _errorText;

		public bool IsOpen
		{
			get
			{
				if ((Object)(object)_canvas != (Object)null)
				{
					return ((Component)_canvas).gameObject.activeInHierarchy;
				}
				return false;
			}
		}

		private void Awake()
		{
			instance = this;
			BuildUI();
		}

		private void BuildUI()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: 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_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Expected O, but got Unknown
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Expected O, but got Unknown
			_canvas = UIHelper.CreateFullscreenCanvas("RTG_CreateDeckScreen", 210);
			UIHelper.CreateDimmedBackground(((Component)_canvas).transform);
			Transform transform = ((Component)_canvas).transform;
			Vector2 anchorMin = new Vector2(0.28f, 0.12f);
			Vector2 anchorMax = new Vector2(0.72f, 0.88f);
			Color? bg = new Color(0.08f, 0.08f, 0.12f, 1f);
			RectTransform parent = UIHelper.CreatePanel(transform, "Panel", anchorMin, anchorMax, default(Vector2), default(Vector2), bg);
			UIHelper.CreateText((Transform)(object)UIHelper.CreatePanel((Transform)(object)parent, "Title", new Vector2(0f, 0.88f), Vector2.one), "TitleText", "Create New Deck", 34, (TextAlignmentOptions)514);
			UIHelper.CreateText((Transform)(object)UIHelper.CreatePanel((Transform)(object)parent, "NameLabel", new Vector2(0.05f, 0.74f), new Vector2(0.95f, 0.82f)), "Lbl", "Deck Name", 22, (TextAlignmentOptions)4097);
			_nameField = UIHelper.CreateInputField((Transform)(object)parent, "NameField", "Enter deck name...", Vector2.zero, Vector2.zero, 22, (ContentType)0);
			RectTransform component = ((Component)_nameField).GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.05f, 0.61f);
			component.anchorMax = new Vector2(0.95f, 0.73f);
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			((UnityEvent<string>)(object)_nameField.onValueChanged).AddListener((UnityAction<string>)delegate
			{
				Validate();
			});
			UIHelper.CreateText((Transform)(object)UIHelper.CreatePanel((Transform)(object)parent, "SizeLabel", new Vector2(0.05f, 0.48f), new Vector2(0.95f, 0.57f)), "Lbl", "Max Deck Size (default 50)", 22, (TextAlignmentOptions)4097);
			_maxSizeField = UIHelper.CreateInputField((Transform)(object)parent, "MaxSizeField", "50", Vector2.zero, Vector2.zero, 22, (ContentType)2);
			RectTransform component2 = ((Component)_maxSizeField).GetComponent<RectTransform>();
			component2.anchorMin = new Vector2(0.05f, 0.35f);
			component2.anchorMax = new Vector2(0.95f, 0.47f);
			offsetMin = (component2.offsetMax = Vector2.zero);
			component2.offsetMin = offsetMin;
			_maxSizeField.text = "50";
			((UnityEvent<string>)(object)_maxSizeField.onValueChanged).AddListener((UnityAction<string>)delegate
			{
				Validate();
			});
			RectTransform parent2 = UIHelper.CreatePanel((Transform)(object)parent, "ErrorPanel", new Vector2(0.05f, 0.26f), new Vector2(0.95f, 0.34f));
			_errorText = UIHelper.CreateText((Transform)(object)parent2, "ErrorText", "", 18, (TextAlignmentOptions)514, (Color?)new Color(1f, 0.35f, 0.35f));
			_createBtn = AnchorButton(parent, "CreateBtn", "Create Deck!", new Vector2(0.12f, 0.12f), new Vector2(0.88f, 0.24f), new Color(0.15f, 0.5f, 0.15f), 26);
			((UnityEvent)_createBtn.onClick).AddListener(new UnityAction(OnCreateClicked));
			((UnityEvent)AnchorButton(parent, "BackBtn", "Back", new Vector2(0.05f, 0.02f), new Vector2(0.4f, 0.1f), new Color(0.3f, 0.3f, 0.3f), 20).onClick).AddListener(new UnityAction(OnBackClicked));
			Validate();
			((Component)_canvas).gameObject.SetActive(false);
		}

		private static Button AnchorButton(RectTransform parent, string name, string label, Vector2 anchorMin, Vector2 anchorMax, Color bgColor, int fontSize)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0030: 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_0044: 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_0063: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = anchorMin;
			obj.anchorMax = anchorMax;
			Vector2 offsetMin = (obj.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = bgColor;
			Button obj2 = val.AddComponent<Button>();
			((Selectable)obj2).targetGraphic = (Graphic)(object)val2;
			ColorBlock colors = default(ColorBlock);
			((ColorBlock)(ref colors)).normalColor = bgColor;
			((ColorBlock)(ref colors)).highlightedColor = bgColor * 1.3f;
			((ColorBlock)(ref colors)).pressedColor = bgColor * 0.7f;
			((ColorBlock)(ref colors)).disabledColor = new Color(0.25f, 0.25f, 0.25f, 0.6f);
			((ColorBlock)(ref colors)).colorMultiplier = 1f;
			((ColorBlock)(ref colors)).fadeDuration = 0.1f;
			((Selectable)obj2).colors = colors;
			GameObject val3 = new GameObject("Label");
			val3.transform.SetParent(val.transform, false);
			RectTransform obj3 = val3.AddComponent<RectTransform>();
			obj3.anchorMin = Vector2.zero;
			obj3.anchorMax = Vector2.one;
			offsetMin = (obj3.offsetMax = Vector2.zero);
			obj3.offsetMin = offsetMin;
			TextMeshProUGUI obj4 = val3.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj4).text = label;
			((TMP_Text)obj4).fontSize = fontSize;
			((TMP_Text)obj4).alignment = (TextAlignmentOptions)514;
			((Graphic)obj4).color = Color.white;
			return obj2;
		}

		public void Show()
		{
			RTGLog.Section("CreateDeckScreen — Show");
			_nameField.text = "";
			_maxSizeField.text = "50";
			((TMP_Text)_errorText).text = "";
			Validate();
			((Component)_canvas).gameObject.SetActive(true);
		}

		public void Hide()
		{
			RTGLog.Section("CreateDeckScreen — Hide");
			((Component)_canvas).gameObject.SetActive(false);
		}

		private void Validate()
		{
			string deckName = _nameField.text.Trim();
			bool flag = deckName.Length > 0;
			bool flag2 = DeckManager.instance?.AllDecks.Find((DeckData d) => d.name == deckName) == null;
			int result;
			bool flag3 = int.TryParse(_maxSizeField.text, out result) && result >= 1;
			string text = "";
			if (deckName.Length > 0 && !flag2)
			{
				text = "A deck with this name already exists.";
			}
			else if (_maxSizeField.text.Length > 0 && !flag3)
			{
				text = "Max size must be a number ≥ 1.";
			}
			((TMP_Text)_errorText).text = text;
			((Selectable)_createBtn).interactable = flag && flag2 && flag3;
		}

		private void OnCreateClicked()
		{
			string text = _nameField.text.Trim();
			int result;
			int num = (int.TryParse(_maxSizeField.text, out result) ? result : 50);
			RTGLog.Section("CreateDeckScreen — Create Deck '" + text + "'");
			RTGLog.Line($"maxSize={num}");
			DeckData deck = DeckManager.instance.CreateDeck(text, num);
			Hide();
			DeckEditorScreen.instance?.Open(deck);
		}

		private void OnBackClicked()
		{
			RTGLog.Section("CreateDeckScreen — Back");
			Hide();
			DeckSelectorScreen.instance?.Show();
		}
	}
	public class DeckEditorScreen : MonoBehaviour
	{
		public static DeckEditorScreen instance;

		private const string MyDeckCategory = "My Deck";

		private const string AllCardsCategory = "All Cards";

		private const string SearchResultsCategory = "Search Results";

		private const int CardsPerPage = 50;

		private const int MinSearchLength = 3;

		private static readonly Color PageIdleColor = new Color(0.15f, 0.15f, 0.22f);

		private static readonly Color PageSelectedColor = Color.white;

		private static readonly Color PageHoverColor = new Color(0.35f, 0.55f, 1f);

		private static readonly Color PagePressedColor = new Color(0.25f, 0.45f, 0.9f);

		private static readonly Color PageSelectedTextColor = new Color(0.1f, 0.1f, 0.15f);

		private static readonly Color PageIdleTextColor = Color.white;

		private DeckData _deck;

		private string _currentCategory;

		private int _currentPage;

		private string _searchQuery = "";

		private bool _isSearchActive;

		private List<CardInfo> _cachedCategoryCards = new List<CardInfo>();

		private Canvas _canvas;

		private TMP_InputField _searchField;

		private TextMeshProUGUI _deckCountText;

		private Transform _cardGridContent;

		private Transform _categoryButtonParent;

		private Transform _pageButtonParent;

		private ScrollRect _cardScrollRect;

		private readonly List<Button> _categoryButtons = new List<Button>();

		private readonly List<string> _categoryButtonNames = new List<string>();

		private readonly List<Button> _pageButtons = new List<Button>();

		private GameObject _maxSizeModal;

		private TMP_InputField _maxSizeModalField;

		private TextMeshProUGUI _maxSizeModalError;

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

		public bool IsOpen
		{
			get
			{
				if ((Object)(object)_canvas != (Object)null)
				{
					return ((Component)_canvas).gameObject.activeInHierarchy;
				}
				return false;
			}
		}

		private void Awake()
		{
			instance = this;
			BuildUI();
		}

		public void Open(DeckData deck)
		{
			RTGLog.Section("DeckEditorScreen — Open deck '" + deck?.name + "'");
			_deck = deck;
			ClearSearch();
			((Component)_canvas).gameObject.SetActive(true);
			BuildCategoryButtons();
			ShowCategory("All Cards");
		}

		private void OnDisable()
		{
			RTGLog.Section("DeckEditorScreen — OnDisable (close)");
			if (_deck == null)
			{
				RTGLog.Line("No deck loaded — nothing to save.");
			}
			else if (_deck.TotalCount <= _deck.maxSize)
			{
				DeckManager.instance?.Save();
				RTGLog.Line($"Auto-saved '{_deck.name}' ({_deck.TotalCount}/{_deck.maxSize} cards).");
			}
			else
			{
				RTGLog.Warn($"Deck over limit ({_deck.TotalCount}/{_deck.maxSize}) — NOT saved.");
			}
		}

		private void BuildUI()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: 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_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: 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_0258: Expected O, but got Unknown
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: 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_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Expected O, but got Unknown
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: 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)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Expected O, but got Unknown
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_0427: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: Unknown result type (might be due to invalid IL or missing references)
			//IL_0474: Unknown result type (might be due to invalid IL or missing references)
			//IL_0480: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04be: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04de: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0508: Unknown result type (might be due to invalid IL or missing references)
			//IL_054a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0554: Expected O, but got Unknown
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_058a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0595: Unknown result type (might be due to invalid IL or missing references)
			//IL_059a: Unknown result type (might be due to invalid IL or missing references)
			//IL_059b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f6: Expected O, but got Unknown
			_canvas = UIHelper.CreateFullscreenCanvas("RTG_DeckEditorScreen", 220);
			UIHelper.CreateDimmedBackground(((Component)_canvas).transform);
			RectTransform parent = UIHelper.CreateStretchPanel(((Component)_canvas).transform, "Outer", 20f, 20f, 20f, 20f, (Color?)new Color(0.06f, 0.06f, 0.09f, 0.97f));
			Vector2 anchorMin = new Vector2(0f, 0.92f);
			Vector2 one = Vector2.one;
			Color? bg = new Color(0.1f, 0.1f, 0.15f, 0.95f);
			RectTransform parent2 = UIHelper.CreatePanel((Transform)(object)parent, "TopBar", anchorMin, one, default(Vector2), default(Vector2), bg);
			_searchField = UIHelper.CreateInputField((Transform)(object)parent2, "SearchField", "Search cards (3+ chars)...", Vector2.zero, Vector2.zero, 20, (ContentType)0);
			RectTransform component = ((Component)_searchField).GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.01f, 0.15f);
			component.anchorMax = new Vector2(0.35f, 0.85f);
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			((UnityEvent<string>)(object)_searchField.onValueChanged).AddListener((UnityAction<string>)OnSearchChanged);
			_deckCountText = UIHelper.CreateText((Transform)(object)parent2, "DeckCountText", "Cards in Deck: 0", 22, (TextAlignmentOptions)4097);
			RectTransform component2 = ((Component)_deckCountText).GetComponent<RectTransform>();
			component2.anchorMin = new Vector2(0.36f, 0f);
			component2.anchorMax = new Vector2(0.65f, 1f);
			offsetMin = (component2.offsetMax = Vector2.zero);
			component2.offsetMin = offsetMin;
			Button obj = UIHelper.CreateButton((Transform)(object)parent2, "ChangeSizeBtn", "Change Max Size", Vector2.zero, Vector2.zero, 18, (Color?)new Color(0.35f, 0.2f, 0.05f), (Color?)null);
			RectTransform component3 = ((Component)obj).GetComponent<RectTransform>();
			component3.anchorMin = new Vector2(0.66f, 0.1f);
			component3.anchorMax = new Vector2(0.85f, 0.9f);
			offsetMin = (component3.offsetMax = Vector2.zero);
			component3.offsetMin = offsetMin;
			((UnityEvent)obj.onClick).AddListener(new UnityAction(OpenMaxSizeModal));
			Button obj2 = UIHelper.CreateButton((Transform)(object)parent2, "CloseBtn", "Close", Vector2.zero, Vector2.zero, 18, (Color?)new Color(0.45f, 0.1f, 0.1f), (Color?)null);
			RectTransform component4 = ((Component)obj2).GetComponent<RectTransform>();
			component4.anchorMin = new Vector2(0.87f, 0.1f);
			component4.anchorMax = new Vector2(0.99f, 0.9f);
			offsetMin = (component4.offsetMax = Vector2.zero);
			component4.offsetMin = offsetMin;
			((UnityEvent)obj2.onClick).AddListener(new UnityAction(CloseScreen));
			Vector2 zero5 = Vector2.zero;
			Vector2 anchorMax = new Vector2(0.18f, 0.92f);
			bg = new Color(0.08f, 0.08f, 0.12f, 0.9f);
			RectTransform component5 = BuildScrollRect((Transform)(object)UIHelper.CreatePanel((Transform)(object)parent, "LeftPanel", zero5, anchorMax, default(Vector2), default(Vector2), bg), "CategoryScroll", out _categoryButtonParent).GetComponent<RectTransform>();
			component5.anchorMin = Vector2.zero;
			component5.anchorMax = Vector2.one;
			offsetMin = (component5.offsetMax = Vector2.zero);
			component5.offsetMin = offsetMin;
			((object)((Component)((Component)_categoryButtonParent).GetComponent<RectTransform>()).GetComponent<VerticalLayoutGroup>())?.GetType();
			VerticalLayoutGroup obj3 = ((Component)_categoryButtonParent).gameObject.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)obj3).spacing = 4f;
			((LayoutGroup)obj3).padding = new RectOffset(4, 4, 4, 4);
			Vector2 anchorMin2 = new Vector2(0.19f, 0f);
			Vector2 anchorMax2 = new Vector2(1f, 0.92f);
			bg = new Color(0.05f, 0.05f, 0.08f, 1f);
			RectTransform parent3 = UIHelper.CreatePanel((Transform)(object)parent, "RightPanel", anchorMin2, anchorMax2, default(Vector2), default(Vector2), bg);
			Vector2 anchorMin3 = new Vector2(0f, 0f);
			Vector2 anchorMax3 = new Vector2(1f, 0.07f);
			bg = new Color(0.08f, 0.08f, 0.12f, 0.95f);
			RectTransform val = UIHelper.CreatePanel((Transform)(object)parent3, "PageBar", anchorMin3, anchorMax3, default(Vector2), default(Vector2), bg);
			GameObject val2 = new GameObject("PageContent");
			val2.transform.SetParent(((Component)val).transform, false);
			RectTransform val3 = val2.AddComponent<RectTransform>();
			val3.anchorMin = Vector2.zero;
			val3.anchorMax = Vector2.one;
			val3.pivot = new Vector2(0f, 0.5f);
			val3.offsetMin = new Vector2(8f, 4f);
			val3.offsetMax = new Vector2(-8f, -4f);
			_pageButtonParent = (Transform)(object)val3;
			HorizontalLayoutGroup obj4 = val2.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj4).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj4).spacing = 6f;
			((LayoutGroup)obj4).padding = new RectOffset(4, 4, 0, 0);
			((LayoutGroup)obj4).childAlignment = (TextAnchor)3;
			GameObject val4 = BuildScrollRect((Transform)(object)parent3, "CardScroll", out _cardGridContent);
			RectTransform component6 = val4.GetComponent<RectTransform>();
			component6.anchorMin = new Vector2(0f, 0.07f);
			component6.anchorMax = Vector2.one;
			offsetMin = (component6.offsetMax = Vector2.zero);
			component6.offsetMin = offsetMin;
			GridLayoutGroup obj5 = ((Component)_cardGridContent).gameObject.AddComponent<GridLayoutGroup>();
			obj5.cellSize = new Vector2(220f, 300f);
			obj5.spacing = new Vector2(10f, 10f);
			((LayoutGroup)obj5).padding = new RectOffset(10, 10, 10, 10);
			obj5.startCorner = (Corner)0;
			obj5.startAxis = (Axis)0;
			((LayoutGroup)obj5).childAlignment = (TextAnchor)0;
			obj5.constraint = (Constraint)0;
			_cardScrollRect = val4.GetComponent<ScrollRect>();
			BuildMaxSizeModal((Transform)(object)parent);
			((Component)_canvas).gameObject.SetActive(false);
		}

		private static GameObject BuildScrollRect(Transform parent, string name, out Transform content, bool horizontal = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001b: 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_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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			Vector2 offsetMin = (obj.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			ScrollRect obj2 = val.AddComponent<ScrollRect>();
			obj2.horizontal = horizontal;
			obj2.vertical = !horizontal;
			obj2.movementType = (MovementType)2;
			obj2.scrollSensitivity = 80f;
			GameObject val2 = new GameObject("Viewport");
			val2.transform.SetParent(val.transform, false);
			RectTransform val3 = val2.AddComponent<RectTransform>();
			val3.anchorMin = Vector2.zero;
			val3.anchorMax = Vector2.one;
			offsetMin = (val3.offsetMax = Vector2.zero);
			val3.offsetMin = offsetMin;
			val3.pivot = (horizontal ? new Vector2(0f, 0.5f) : new Vector2(0f, 1f));
			((Graphic)val2.AddComponent<Image>()).color = new Color(1f, 1f, 1f, 0.01f);
			val2.AddComponent<Mask>().showMaskGraphic = false;
			obj2.viewport = val3;
			GameObject val4 = new GameObject("Content");
			val4.transform.SetParent(val2.transform, false);
			RectTransform val5 = val4.AddComponent<RectTransform>();
			if (horizontal)
			{
				val5.anchorMin = new Vector2(0f, 0f);
				val5.anchorMax = new Vector2(0f, 1f);
				val5.pivot = new Vector2(0f, 0.5f);
			}
			else
			{
				val5.anchorMin = new Vector2(0f, 1f);
				val5.anchorMax = new Vector2(1f, 1f);
				val5.pivot = new Vector2(0f, 1f);
			}
			val5.sizeDelta = Vector2.zero;
			val5.anchoredPosition = Vector2.zero;
			ContentSizeFitter val6 = val4.AddComponent<ContentSizeFitter>();
			if (horizontal)
			{
				val6.horizontalFit = (FitMode)2;
				val6.verticalFit = (FitMode)0;
			}
			else
			{
				val6.horizontalFit = (FitMode)0;
				val6.verticalFit = (FitMode)2;
			}
			obj2.content = val5;
			content = (Transform)(object)val5;
			return val;
		}

		private void BuildCategoryButtons()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			RTGLog.Section("DeckEditorScreen — BuildCategoryButtons");
			foreach (Transform item in _categoryButtonParent)
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			_categoryButtons.Clear();
			_categoryButtonNames.Clear();
			RTGLog.Line($"CardManager.categories.Count = {CardManager.categories.Count}");
			if (CardManager.categories.Count == 0)
			{
				RTGLog.Warn("No categories found in CardManager!");
			}
			AddCategoryButton("My Deck");
			AddCategoryButton("All Cards");
			foreach (string category in CardManager.categories)
			{
				AddCategoryButton(category);
			}
			Canvas.ForceUpdateCanvases();
			Transform categoryButtonParent = _categoryButtonParent;
			LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((categoryButtonParent is RectTransform) ? categoryButtonParent : null));
			RTGLog.Line($"Built {_categoryButtons.Count} category button(s).");
		}

		private void AddCategoryButton(string cat)
		{
			RTGLog.Line("  Adding category button: '" + cat + "'");
			string captured = cat;
			Button item = CreateCategoryButton(_categoryButtonParent, cat, delegate
			{
				ShowCategory(captured);
			});
			_categoryButtons.Add(item);
			_categoryButtonNames.Add(cat);
		}

		private void ShowCategory(string category)
		{
			RTGLog.Section("DeckEditorScreen — ShowCategory '" + category + "'");
			if (_isSearchActive && category != "Search Results")
			{
				ClearSearch();
			}
			_isSearchActive = false;
			_currentCategory = category;
			_currentPage = 0;
			_cachedCategoryCards = GetCardsForCategory(category);
			RTGLog.Line($"Resolved {_cachedCategoryCards.Count} card(s) for category '{category}'.");
			UpdateCategoryButtonStyles();
			RebuildPageButtons();
			ShowPage(0);
		}

		private void ShowPage(int page)
		{
			int pageCount = GetPageCount();
			_currentPage = Mathf.Clamp(page, 0, Mathf.Max(0, pageCount - 1));
			ClearCardRows();
			if (_cachedCategoryCards.Count == 0)
			{
				RTGLog.Warn("No cards found for category '" + _currentCategory + "'.");
				UpdatePageButtonStyles();
				UpdateDeckCountDisplay();
				return;
			}
			int num = _currentPage * 50;
			int num2 = Mathf.Min(num + 50, _cachedCategoryCards.Count);
			int num3 = 0;
			for (int i = num; i < num2; i++)
			{
				CardInfo val = _cachedCategoryCards[i];
				if (!((Object)(object)val == (Object)null))
				{
					BuildCardRow(val);
					num3++;
				}
			}
			RTGLog.Line($"Built {num3} card row(s) for '{_currentCategory}' page {_currentPage + 1}/{pageCount}.");
			if ((Object)(object)_cardScrollRect != (Object)null)
			{
				_cardScrollRect.verticalNormalizedPosition = 1f;
			}
			Canvas.ForceUpdateCanvases();
			Transform cardGridContent = _cardGridContent;
			LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((cardGridContent is RectTransform) ? cardGridContent : null));
			UpdatePageButtonStyles();
			UpdateDeckCountDisplay();
		}

		private void ClearCardRows()
		{
			foreach (GameObject cardRow in _cardRows)
			{
				if ((Object)(object)cardRow != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)cardRow);
				}
			}
			_cardRows.Clear();
		}

		private int GetPageCount()
		{
			if (_cachedCategoryCards.Count != 0)
			{
				return Mathf.CeilToInt((float)_cachedCategoryCards.Count / 50f);
			}
			return 1;
		}

		private void RebuildPageButtons()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			foreach (Transform item2 in _pageButtonParent)
			{
				Object.Destroy((Object)(object)((Component)item2).gameObject);
			}
			_pageButtons.Clear();
			int pageCount = GetPageCount();
			for (int i = 0; i < pageCount; i++)
			{
				int pageIndex = i;
				string label = (i + 1).ToString();
				Button item = CreatePageButton(_pageButtonParent, label, pageIndex);
				_pageButtons.Add(item);
			}
			Canvas.ForceUpdateCanvases();
			Transform pageButtonParent = _pageButtonParent;
			LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((pageButtonParent is RectTransform) ? pageButtonParent : null));
		}

		private Button CreateCategoryButton(Transform parent, string label, Action onClick)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Cat_" + label);
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0f, 1f);
			obj.anchorMax = new Vector2(1f, 1f);
			obj.pivot = new Vector2(0.5f, 1f);
			obj.sizeDelta = new Vector2(0f, 44f);
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = PageIdleColor;
			((Graphic)val2).raycastTarget = true;
			Button val3 = val.AddComponent<Button>();
			((Selectable)val3).targetGraphic = (Graphic)(object)val2;
			((UnityEvent)val3.onClick).AddListener((UnityAction)delegate
			{
				onClick();
			});
			LayoutElement obj2 = val.AddComponent<LayoutElement>();
			obj2.preferredHeight = 44f;
			obj2.minHeight = 44f;
			obj2.flexibleHeight = 0f;
			AddNavButtonLabel(val.transform, label, 18, (TextAlignmentOptions)514);
			return val3;
		}

		private Button CreatePageButton(Transform parent, string label, int pageIndex)
		{
			//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_0031: 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_0057: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Page_" + label);
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0f, 0f);
			obj.anchorMax = new Vector2(0f, 1f);
			obj.pivot = new Vector2(0f, 0.5f);
			obj.sizeDelta = new Vector2(40f, 0f);
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = PageIdleColor;
			((Graphic)val2).raycastTarget = true;
			Button val3 = val.AddComponent<Button>();
			((Selectable)val3).targetGraphic = (Graphic)(object)val2;
			((UnityEvent)val3.onClick).AddListener((UnityAction)delegate
			{
				ShowPage(pageIndex);
			});
			LayoutElement obj2 = val.AddComponent<LayoutElement>();
			obj2.preferredWidth = 40f;
			obj2.minWidth = 40f;
			obj2.flexibleWidth = 0f;
			AddNavButtonLabel(val.transform, label, 18, (TextAlignmentOptions)514);
			return val3;
		}

		private static void AddNavButtonLabel(Transform parent, string text, int fontSize, TextAlignmentOptions alignment)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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 val = new GameObject("Label");
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			obj.offsetMin = Vector2.zero;
			obj.offsetMax = Vector2.zero;
			TextMeshProUGUI obj2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj2).text = text;
			((TMP_Text)obj2).fontSize = fontSize;
			((TMP_Text)obj2).alignment = alignment;
			((Graphic)obj2).color = PageIdleTextColor;
			((Graphic)obj2).raycastTarget = false;
		}

		private void UpdateCategoryButtonStyles()
		{
			for (int i = 0; i < _categoryButtons.Count; i++)
			{
				Button val = _categoryButtons[i];
				if (!((Object)(object)val == (Object)null))
				{
					bool selected = !_isSearchActive && i < _categoryButtonNames.Count && _categoryButtonNames[i] == _currentCategory;
					ApplyNavButtonStyle(val, selected);
				}
			}
		}

		private void UpdatePageButtonStyles()
		{
			for (int i = 0; i < _pageButtons.Count; i++)
			{
				Button val = _pageButtons[i];
				if (!((Object)(object)val == (Object)null))
				{
					bool selected = i == _currentPage;
					ApplyNavButtonStyle(val, selected);
				}
			}
		}

		private static void ApplyNavButtonStyle(Button btn, bool selected)
		{
			//IL_001b: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0062: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			Image component = ((Component)btn).GetComponent<Image>();
			if (!((Object)(object)component == (Object)null))
			{
				Color val = (selected ? PageSelectedColor : PageIdleColor);
				Color highlightedColor = (selected ? PageSelectedColor : PageHoverColor);
				Color pressedColor = (Color)(selected ? new Color(0.9f, 0.9f, 0.9f) : PagePressedColor);
				((Graphic)component).color = val;
				ColorBlock colors = default(ColorBlock);
				((ColorBlock)(ref colors)).normalColor = val;
				((ColorBlock)(ref colors)).highlightedColor = highlightedColor;
				((ColorBlock)(ref colors)).pressedColor = pressedColor;
				((ColorBlock)(ref colors)).disabledColor = new Color(0.3f, 0.3f, 0.3f, 0.5f);
				((ColorBlock)(ref colors)).colorMultiplier = 1f;
				((ColorBlock)(ref colors)).fadeDuration = 0.08f;
				((Selectable)btn).colors = colors;
				TextMeshProUGUI componentInChildren = ((Component)btn).GetComponentInChildren<TextMeshProUGUI>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((Graphic)componentInChildren).color = (selected ? PageSelectedTextColor : PageIdleTextColor);
				}
			}
		}

		private List<CardInfo> GetCardsForCategory(string category)
		{
			if (category == "My Deck")
			{
				return GetMyDeckCards();
			}
			if (category == "All Cards")
			{
				return GetAllCardsAlphabetical();
			}
			string[] cardsInCategory = CardManager.GetCardsInCategory(category);
			if (cardsInCategory == null || cardsInCategory.Length == 0)
			{
				return new List<CardInfo>();
			}
			List<CardInfo> list = new List<CardInfo>(cardsInCategory.Length);
			string[] array = cardsInCategory;
			for (int i = 0; i < array.Length; i++)
			{
				CardInfo cardInfoWithName = CardManager.GetCardInfoWithName(array[i]);
				if ((Object)(object)cardInfoWithName != (Object)null)
				{
					list.Add(cardInfoWithName);
				}
			}
			SortCardsAlphabeticalThenRarity(list);
			return list;
		}

		private List<CardInfo> GetAllCardsAlphabetical()
		{
			List<CardInfo> list = new List<CardInfo>(CardManager.cards.Count);
			foreach (string key in CardManager.cards.Keys)
			{
				CardInfo cardInfoWithName = CardManager.GetCardInfoWithName(key);
				if ((Object)(object)cardInfoWithName != (Object)null)
				{
					list.Add(cardInfoWithName);
				}
			}
			SortCardsAlphabeticalThenRarity(list);
			return list;
		}

		private List<CardInfo> GetMyDeckCards()
		{
			List<CardInfo> list = new List<CardInfo>();
			if (_deck?.cards == null)
			{
				return list;
			}
			foreach (CardEntry card in _deck.cards)
			{
				if (card != null && card.count > 0 && !string.IsNullOrEmpty(card.cardObjectName))
				{
					CardInfo cardInfoWithName = CardManager.GetCardInfoWithName(card.cardObjectName);
					if ((Object)(object)cardInfoWithName != (Object)null)
					{
						list.Add(cardInfoWithName);
					}
				}
			}
			SortCardsAlphabeticalThenRarity(list);
			return list;
		}

		private void RefreshMyDeckViewIfActive()
		{
			if (!(_currentCategory != "My Deck"))
			{
				_cachedCategoryCards = GetMyDeckCards();
				int pageCount = GetPageCount();
				if (_currentPage >= pageCount)
				{
					_currentPage = Mathf.Max(0, pageCount - 1);
				}
				RebuildPageButtons();
				ShowPage(_currentPage);
			}
		}

		private void OnSearchChanged(string query)
		{
			_searchQuery = query?.Trim() ?? "";
			if (_searchQuery.Length >= 3)
			{
				_isSearchActive = true;
				_currentCategory = "Search Results";
				_currentPage = 0;
				_cachedCategoryCards = SearchCards(_searchQuery);
				RTGLog.Line($"Search '{_searchQuery}' found {_cachedCategoryCards.Count} card(s).");
				UpdateCategoryButtonStyles();
				RebuildPageButtons();
				ShowPage(0);
			}
			else if (_isSearchActive)
			{
				_isSearchActive = false;
				ShowCategory("All Cards");
			}
		}

		private List<CardInfo> SearchCards(string query)
		{
			List<CardInfo> list = new List<CardInfo>();
			if (string.IsNullOrEmpty(query))
			{
				return list;
			}
			string value = query.ToLowerInvariant();
			foreach (string key in CardManager.cards.Keys)
			{
				CardInfo cardInfoWithName = CardManager.GetCardInfoWithName(key);
				if (!((Object)(object)cardInfoWithName == (Object)null))
				{
					bool num = !string.IsNullOrEmpty(cardInfoWithName.cardName) && cardInfoWithName.cardName.ToLowerInvariant().Contains(value);
					bool flag = !string.IsNullOrEmpty(cardInfoWithName.cardDestription) && cardInfoWithName.cardDestription.ToLowerInvariant().Contains(value);
					if (num || flag)
					{
						list.Add(cardInfoWithName);
					}
				}
			}
			SortCardsAlphabeticalThenRarity(list);
			return list;
		}

		private void ClearSearch()
		{
			if ((Object)(object)_searchField != (Object)null)
			{
				_searchField.text = "";
			}
			_searchQuery = "";
			_isSearchActive = false;
		}

		private static void SortCardsAlphabeticalThenRarity(List<CardInfo> cards)
		{
			cards.Sort(delegate(CardInfo a, CardInfo b)
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				int num = CompareFirstLetter(a?.cardName, b?.cardName);
				if (num != 0)
				{
					return num;
				}
				int num2 = ((Enum)(Rarity)(ref a.rarity)).CompareTo((object?)b.rarity);
				return (num2 != 0) ? num2 : string.Compare(a.cardName, b.cardName, StringComparison.OrdinalIgnoreCase);
			});
		}

		private static int CompareFirstLetter(string a, string b)
		{
			char sortLetter = GetSortLetter(a);
			char sortLetter2 = GetSortLetter(b);
			return sortLetter.CompareTo(sortLetter2);
		}

		private static char GetSortLetter(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return '\0';
			}
			return char.ToUpperInvariant(name[0]);
		}

		private void BuildCardRow(CardInfo cardInfo)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: 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_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: 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_0225: Expected O, but got Unknown
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Expected O, but got Unknown
			//IL_02c1: 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_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Expected O, but got Unknown
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_0467: Unknown result type (might be due to invalid IL or missing references)
			//IL_048d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a9: Expected O, but got Unknown
			//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04db: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_053d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_055f: Expected O, but got Unknown
			//IL_0589: Unknown result type (might be due to invalid IL or missing references)
			//IL_059e: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0605: Unknown result type (might be due to invalid IL or missing references)
			//IL_0623: Unknown result type (might be due to invalid IL or missing references)
			//IL_0647: Unknown result type (might be due to invalid IL or missing references)
			//IL_0652: Unknown result type (might be due to invalid IL or missing references)
			//IL_065d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0662: Unknown result type (might be due to invalid IL or missing references)
			//IL_0663: Unknown result type (might be due to invalid IL or missing references)
			//IL_066a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0693: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cb: Expected O, but got Unknown
			//IL_06d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e3: Expected O, but got Unknown
			//IL_06ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f9: Expected O, but got Unknown
			string name = ((Object)((Component)cardInfo).gameObject).name;
			CardEntry entry = GetOrCreateEntry(name);
			int maxCount = DeckManager.MaxCountForCard(cardInfo);
			GameObject val = new GameObject("Card_" + name);
			val.transform.SetParent(_cardGridContent, false);
			val.AddComponent<RectTransform>().sizeDelta = new Vector2(220f, 300f);
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredWidth = 220f;
			obj.preferredHeight = 300f;
			_cardRows.Add(val);
			Image bgImg = val.AddComponent<Image>();
			((Graphic)bgImg).color = new Color(0.1f, 0.1f, 0.15f, 1f);
			((Graphic)bgImg).raycastTarget = true;
			SetupCardVisual(cardInfo, val);
			GameObject val2 = new GameObject("RarityLabel");
			val2.transform.SetParent(val.transform, false);
			RectTransform obj2 = val2.AddComponent<RectTransform>();
			obj2.anchorMin = new Vector2(0f, 0f);
			obj2.anchorMax = new Vector2(1f, 0.12f);
			Vector2 offsetMin = (obj2.offsetMax = Vector2.zero);
			obj2.offsetMin = offsetMin;
			Image obj3 = val2.AddComponent<Image>();
			((Graphic)obj3).color = new Color(0f, 0f, 0f, 0.7f);
			((Graphic)obj3).raycastTarget = false;
			GameObject val3 = new GameObject("RarityText");
			val3.transform.SetParent(val2.transform, false);
			RectTransform obj4 = val3.AddComponent<RectTransform>();
			obj4.anchorMin = Vector2.zero;
			obj4.anchorMax = Vector2.one;
			offsetMin = (obj4.offsetMax = Vector2.zero);
			obj4.offsetMin = offsetMin;
			TextMeshProUGUI obj5 = val3.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj5).text = $"{cardInfo.cardName} ({cardInfo.rarity})";
			((TMP_Text)obj5).fontSize = 11f;
			((TMP_Text)obj5).alignment = (TextAlignmentOptions)514;
			((Graphic)obj5).color = RarityColor(cardInfo.rarity);
			((TMP_Text)obj5).enableWordWrapping = false;
			((TMP_Text)obj5).overflowMode = (TextOverflowModes)1;
			((Graphic)obj5).raycastTarget = false;
			GameObject controlsGo = new GameObject("Controls");
			controlsGo.transform.SetParent(val.transform, false);
			RectTransform obj6 = controlsGo.AddComponent<RectTransform>();
			obj6.anchorMin = Vector2.zero;
			obj6.anchorMax = Vector2.one;
			offsetMin = (obj6.offsetMax = Vector2.zero);
			obj6.offsetMin = offsetMin;
			controlsGo.SetActive(entry.count > 0);
			GameObject val4 = new GameObject("MinusBtn");
			val4.transform.SetParent(controlsGo.transform, false);
			RectTransform obj7 = val4.AddComponent<RectTransform>();
			obj7.anchorMin = new Vector2(0f, 0f);
			obj7.anchorMax = new Vector2(0f, 0f);
			obj7.pivot = new Vector2(0f, 0f);
			obj7.anchoredPosition = new Vector2(4f, 4f);
			obj7.sizeDelta = new Vector2(36f, 36f);
			Image val5 = val4.AddComponent<Image>();
			((Graphic)val5).color = new Color(0.7f, 0.15f, 0.15f, 0.95f);
			Button val6 = val4.AddComponent<Button>();
			((Selectable)val6).targetGraphic = (Graphic)(object)val5;
			TextMeshProUGUI obj8 = new GameObject("Text").AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj8).transform.SetParent(val4.transform, false);
			RectTransform component = ((Component)obj8).GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			((TMP_Text)obj8).text = "-";
			((Graphic)obj8).raycastTarget = false;
			((TMP_Text)obj8).fontSize = 24f;
			((TMP_Text)obj8).alignment = (TextAlignmentOptions)514;
			((Graphic)obj8).color = Color.white;
			GameObject val7 = new GameObject("CountLabel");
			val7.transform.SetParent(controlsGo.transform, false);
			RectTransform obj9 = val7.AddComponent<RectTransform>();
			obj9.anchorMin = new Vector2(0.5f, 0f);
			obj9.anchorMax = new Vector2(0.5f, 0f);
			obj9.pivot = new Vector2(0.5f, 0f);
			obj9.anchoredPosition = new Vector2(0f, 4f);
			obj9.sizeDelta = new Vector2(40f, 36f);
			Image obj10 = val7.AddComponent<Image>();
			((Graphic)obj10).color = new Color(0f, 0f, 0f, 0.8f);
			((Graphic)obj10).raycastTarget = false;
			GameObject val8 = new GameObject("CountText");
			val8.transform.SetParent(val7.transform, false);
			RectTransform obj11 = val8.AddComponent<RectTransform>();
			obj11.anchorMin = Vector2.zero;
			obj11.anchorMax = Vector2.one;
			offsetMin = (obj11.offsetMax = Vector2.zero);
			obj11.offsetMin = offsetMin;
			TextMeshProUGUI countTmp = val8.AddComponent<TextMeshProUGUI>();
			((TMP_Text)countTmp).text = entry.count.ToString();
			((TMP_Text)countTmp).fontSize = 22f;
			((TMP_Text)countTmp).alignment = (TextAlignmentOptions)514;
			((Graphic)countTmp).color = Color.white;
			((Graphic)countTmp).raycastTarget = false;
			GameObject val9 = new GameObject("PlusBtn");
			val9.transform.SetParent(controlsGo.transform, false);
			RectTransform obj12 = val9.AddComponent<RectTransform>();
			obj12.anchorMin = new Vector2(1f, 0f);
			obj12.anchorMax = new Vector2(1f, 0f);
			obj12.pivot = new Vector2(1f, 0f);
			obj12.anchoredPosition = new Vector2(-4f, 4f);
			obj12.sizeDelta = new Vector2(36f, 36f);
			Image val10 = val9.AddComponent<Image>();
			((Graphic)val10).color = new Color(0.15f, 0.6f, 0.15f, 0.95f);
			Button obj13 = val9.AddComponent<Button>();
			((Selectable)obj13).targetGraphic = (Graphic)(object)val10;
			TextMeshProUGUI obj14 = new GameObject("Text").AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj14).transform.SetParent(val9.transform, false);
			RectTransform component2 = ((Component)obj14).GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			offsetMin = (component2.offsetMax = Vector2.zero);
			component2.offsetMin = offsetMin;
			((TMP_Text)obj14).text = "+";
			((TMP_Text)obj14).fontSize = 24f;
			((TMP_Text)obj14).alignment = (TextAlignmentOptions)514;
			((Graphic)obj14).color = Color.white;
			((Graphic)obj14).raycastTarget = false;
			Button obj15 = val.AddComponent<Button>();
			((Selectable)obj15).targetGraphic = (Graphic)(object)bgImg;
			((UnityEvent)obj15.onClick).AddListener((UnityAction)delegate
			{
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				if (entry.count == 0)
				{
					entry.count = 1;
					controlsGo.SetActive(true);
					((TMP_Text)countTmp).text = "1";
					((Graphic)bgImg).color = new Color(0.15f, 0.25f, 0.15f, 0.9f);
					UpdateDeckCountDisplay();
				}
			});
			((UnityEvent)val6.onClick).AddListener((UnityAction)delegate
			{
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				if (entry.count > 0)
				{
					entry.count--;
					((TMP_Text)countTmp).text = entry.count.ToString();
					if (entry.count == 0)
					{
						controlsGo.SetActive(false);
						((Graphic)bgImg).color = new Color(0.1f, 0.1f, 0.14f, 0.85f);
						UpdateDeckCountDisplay();
						RefreshMyDeckViewIfActive();
					}
					else
					{
						UpdateDeckCountDisplay();
					}
				}
			});
			((UnityEvent)obj13.onClick).AddListener((UnityAction)delegate
			{
				if (entry.count < maxCount)
				{
					entry.count++;
					((TMP_Text)countTmp).text = entry.count.ToString();
					UpdateDeckCountDisplay();
				}
			});
		}

		private void SetupCardVisual(CardInfo cardInfo, GameObject parent)
		{
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: 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_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			RTGLog.Line("SetupCardVisual '" + cardInfo.cardName + "': cardArt=" + (((Object)(object)cardInfo.cardArt != (Object)null) ? ((Object)cardInfo.cardArt).name : "NULL"));
			GameObject val = Object.Instantiate<GameObject>(((Component)cardInfo).gameObject, parent.transform);
			((Object)val).name = "CardVisual";
			val.SetActive(true);
			GameObject val2 = FindChildByName(val, "Back");
			if ((Object)(object)val2 != (Object)null)
			{
				Object.Destroy((Object)(object)val2);
			}
			GameObject val3 = FindChildByName(val, "Damagable");
			if ((Object)(object)val3 != (Object)null)
			{
				Object.Destroy((Object)(object)val3);
			}
			GameObject val4 = FindChildByName(val, "UI_ParticleSystem");
			if ((Object)(object)val4 != (Object)null)
			{
				Object.Destroy((Object)(object)val4);
			}
			GameObject val5 = FindChildByName(val, "BlockFront");
			if ((Object)(object)val5 != (Object)null)
			{
				val5.SetActive(false);
			}
			CanvasGroup[] componentsInChildren = val.GetComponentsInChildren<CanvasGroup>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].alpha = 1f;
			}
			CardVisuals[] componentsInChildren2 = val.GetComponentsInChildren<CardVisuals>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].firstValueToSet = true;
			}
			Animator[] componentsInChildren3 = val.GetComponentsInChildren<Animator>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				((Behaviour)componentsInChildren3[i]).enabled = false;
			}
			CurveAnimation[] componentsInChildren4 = val.GetComponentsInChildren<CurveAnimation>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				((Behaviour)componentsInChildren4[i]).enabled = false;
			}
			RectTransform orAddComponent = ExtensionMethods.GetOrAddComponent<RectTransform>(val, false);
			((Transform)orAddComponent).localScale = Vector3.one * 15f;
			orAddComponent.anchorMin = new Vector2(0.5f, 0.5f);
			orAddComponent.anchorMax = new Vector2(0.5f, 0.5f);
			orAddComponent.pivot = new Vector2(0.5f, 0.5f);
			orAddComponent.anchoredPosition = new Vector2(0f, 10f);
			Graphic[] componentsInChildren5 = val.GetComponentsInChildren<Graphic>(true);
			for (int i = 0; i < componentsInChildren5.Length; i++)
			{
				componentsInChildren5[i].raycastTarget = false;
			}
			if ((Object)(object)cardInfo.cardArt != (Object)null)
			{
				GameObject val6 = FindChildByName(val, "Art");
				RTGLog.Line("SetupCardVisual '" + cardInfo.cardName + "': Art transform=" + (((Object)(object)val6 != (Object)null) ? ((Object)val6).name : "NOT FOUND"));
				if ((Object)(object)val6 != (Object)null)
				{
					GameObject val7 = Object.Instantiate<GameObject>(cardInfo.cardArt, val6.transform);
					val7.transform.SetAsFirstSibling();
					RectTransform component = val7.GetComponent<RectTransform>();
					if ((Object)(object)component != (Object)null)
					{
						component.anchorMin = Vector2.zero;
						component.anchorMax = Vector2.one;
						component.offsetMin = Vector2.zero;
						component.offsetMax = Vector2.zero;
						((Transform)component).localPosition = Vector3.zero;
						((Transform)component).localScale = Vector3.one;
						RTGLog.Line("SetupCardVisual '" + cardInfo.cardName + "': Art RectTransform reset to fill parent.");
					}
					else
					{
						val7.transform.localPosition = Vector3.zero;
						val7.transform.localScale = Vector3.one;
					}
					RTGLog.Line("SetupCardVisual '" + cardInfo.cardName + "': Art placed successfully.");
				}
				else
				{
					RTGLog.Warn("SetupCardVisual '" + cardInfo.cardName + "': 'Art' child not found — cannot place card art.");
				}
			}
			else
			{
				RTGLog.Line("SetupCardVisual '" + cardInfo.cardName + "': no cardArt set, skipping art placement.");
			}
		}

		private static GameObject FindChildByName(GameObject parent, string name)
		{
			Transform[] componentsInChildren = parent.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (((Object)val).name == name)
				{
					return ((Component)val).gameObject;
				}
			}
			return null;
		}

		private CardEntry GetOrCreateEntry(string cardObjectName)
		{
			CardEntry cardEntry = _deck.cards.Find((CardEntry e) => e.cardObjectName == cardObjectName);
			if (cardEntry == null)
			{
				cardEntry = new CardEntry
				{
					cardObjectName = cardObjectName,
					count = 0
				};
				_deck.cards.Add(cardEntry);
			}
			return cardEntry;
		}

		private void UpdateDeckCountDisplay()
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if (_deck != null)
			{
				int totalCount = _deck.TotalCount;
				if (_isSearchActive)
				{
					((TMP_Text)_deckCountText).text = $"Found {_cachedCategoryCards.Count} cards — Deck: {totalCount} / {_deck.maxSize}";
				}
				else
				{
					((TMP_Text)_deckCountText).text = $"Cards in Deck: {totalCount} / {_deck.maxSize}";
				}
				((Graphic)_deckCountText).color = (Color)((totalCount > _deck.maxSize) ? new Color(1f, 0.3f, 0.3f) : Color.white);
			}
		}

		private void BuildMaxSizeModal(Transform parent)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0045: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: 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)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Expected O, but got Unknown
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Expected O, but got Unknown
			_maxSizeModal = new GameObject("MaxSizeModal");
			_maxSizeModal.transform.SetParent(parent, false);
			_maxSizeModal.SetActive(false);
			RectTransform val = _maxSizeModal.AddComponent<RectTransform>();
			val.anchorMin = new Vector2(0.3f, 0.35f);
			val.anchorMax = new Vector2(0.7f, 0.65f);
			Vector2 offsetMin = (val.offsetMax = Vector2.zero);
			val.offsetMin = offsetMin;
			((Graphic)_maxSizeModal.AddComponent<Image>()).color = new Color(0.08f, 0.08f, 0.14f, 0.98f);
			UIHelper.CreateText((Transform)(object)val, "Title", "Change Max Deck Size", 26, (TextAlignmentOptions)514);
			_maxSizeModalField = UIHelper.CreateInputField((Transform)(object)val, "SizeField", _deck?.maxSize.ToString() ?? "50", Vector2.zero, Vector2.zero, 22, (ContentType)2);
			RectTransform component = ((Component)_maxSizeModalField).GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.1f, 0.38f);
			component.anchorMax = new Vector2(0.9f, 0.55f);
			offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			((UnityEvent<string>)(object)_maxSizeModalField.onValueChanged).AddListener((UnityAction<string>)delegate
			{
				ValidateModal();
			});
			_maxSizeModalError = UIHelper.CreateText((Transform)(object)val, "ModalError", "", 17, (TextAlignmentOptions)514, (Color?)new Color(1f, 0.35f, 0.35f));
			RectTransform component2 = ((Component)_maxSizeModalError).GetComponent<RectTransform>();
			component2.anchorMin = new Vector2(0.05f, 0.25f);
			component2.anchorMax = new Vector2(0.95f, 0.37f);
			offsetMin = (component2.offsetMax = Vector2.zero);
			component2.offsetMin = offsetMin;
			Button obj = UIHelper.CreateButton((Transform)(object)val, "ConfirmBtn", "Confirm", Vector2.zero, Vector2.zero, 22, (Color?)new Color(0.15f, 0.5f, 0.15f), (Color?)null);
			RectTransform component3 = ((Component)obj).GetComponent<RectTransform>();
			component3.anchorMin = new Vector2(0.1f, 0.06f);
			component3.anchorMax = new Vector2(0.55f, 0.23f);
			offsetMin = (component3.offsetMax = Vector2.zero);
			component3.offsetMin = offsetMin;
			((UnityEvent)obj.onClick).AddListener(new UnityAction(ConfirmMaxSize));
			Button obj2 = UIHelper.CreateButton((Transform)(object)val, "CancelBtn", "Cancel", Vector2.zero, Vector2.zero, 22, (Color?)new Color(0.45f, 0.1f, 0.1f), (Color?)null);
			RectTransform component4 = ((Component)obj2).GetComponent<RectTransform>();
			component4.anchorMin = new Vector2(0.57f, 0.06f);
			component4.anchorMax = new Vector2(0.9f, 0.23f);
			offsetMin = (component4.offsetMax = Vector2.zero);
			component4.offsetMin = offsetMin;
			((UnityEvent)obj2.onClick).AddListener((UnityAction)delegate
			{
				_maxSizeModal.SetActive(false);
			});
		}

		private void OpenMaxSizeModal()
		{
			if (_deck != null)
			{
				RTGLog.Section($"DeckEditorScreen — Change Max Size (current={_deck.maxSize})");
				_maxSizeModalField.text = _deck.maxSize.ToString();
				((TMP_Text)_maxSizeModalError).text = "";
				_maxSizeModal.SetActive(true);
			}
		}

		private void ValidateModal()
		{
			int result;
			bool flag = int.TryParse(_maxSizeModalField.text, out result) && result >= 1;
			((TMP_Text)_maxSizeModalError).text = (flag ? "" : "Must be a number ≥ 1.");
		}

		private void ConfirmMaxSize()
		{
			if (int.TryParse(_maxSizeModalField.text, out var result) && result >= 1)
			{
				RTGLog.Section($"DeckEditorScreen — Confirm Max Size {result}");
				_deck.maxSize = result;
				UpdateDeckCountDisplay();
				_maxSizeModal.SetActive(false);
				DeckManager.instance?.Save();
			}
		}

		private void CloseScreen()
		{
			RTGLog.Section("DeckEditorScreen — Close");
			((Component)_canvas).gameObject.SetActive(false);
			DeckSelectorScreen.instance?.Show();
		}

		private static Color RarityColor(Rarity rarity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			return (Color)((int)rarity switch
			{
				0 => new Color(0.6f, 0.6f, 0.6f), 
				1 => new Color(0.2f, 0.8f, 0.2f), 
				2 => new Color(0.2f, 0.4f, 1f), 
				_ => new Color(1f, 0.65f, 0f), 
			});
		}
	}
	public class DeckSelectorScreen : MonoBehaviour
	{
		public static DeckSelectorScreen instance;

		private Canvas _canvas;

		private Button _createBtn;

		private Button _editBtn;

		private Button _deleteBtn;

		private TextMeshProUGUI _deleteBtnLabel;

		private TMP_Dropdown _deckDropdown;

		private TextMeshProUGUI _activeDeckLabel;

		private GameObject _deleteModal;

		private TextMeshProUGUI _deleteModalMessage;

		private string _pendingDeleteDeckName;

		public bool IsOpen
		{
			get
			{
				if ((Object)(object)_canvas != (Object)null)
				{
					return ((Component)_canvas).gameObject.activeInHierarchy;
				}
				return false;
			}
		}

		private void Awake()
		{
			instance = this;
			BuildUI();
		}

		private void BuildUI()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00b5: 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_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Expected O, but got Unknown
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Expected O, but got Unknown
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e7: Expected O, but got Unknown
			_canvas = UIHelper.CreateFullscreenCanvas("RTG_DeckSelectorScreen", 200);
			UIHelper.CreateDimmedBackground(((Component)_canvas).transform);
			Transform transform = ((Component)_canvas).transform;
			Vector2 anchorMin = new Vector2(0.3f, 0.15f);
			Vector2 anchorMax = new Vector2(0.7f, 0.85f);
			Color? bg = new Color(0.08f, 0.08f, 0.12f, 1f);
			RectTransform parent = UIHelper.CreatePanel(transform, "Panel", anchorMin, anchorMax, default(Vector2), default(Vector2), bg);
			UIHelper.CreateText((Transform)(object)UIHelper.CreatePanel((Transform)(object)parent, "Title", new Vector2(0f, 0.85f), Vector2.one), "TitleText", "Your Decks", 38, (TextAlignmentOptions)514);
			_createBtn = AnchorButton(parent, "CreateBtn", "Create New Deck", new Vector2(0.08f, 0.74f), new Vector2(0.92f, 0.85f), new Color(0.15f, 0.5f, 0.15f), 26);
			((UnityEvent)_createBtn.onClick).AddListener(new UnityAction(OnCreateClicked));
			_editBtn = AnchorButton(parent, "EditBtn", "Edit Deck", new Vector2(0.08f, 0.6f), new Vector2(0.92f, 0.72f), new Color(0.2f, 0.3f, 0.55f), 26);
			((UnityEvent)_editBtn.onClick).AddListener(new UnityAction(OnEditClicked));
			_deckDropdown = BuildDropdown(parent, new Vector2(0.08f, 0.46f), new Vector2(0.92f, 0.58f));
			((UnityEvent)AnchorButton(parent, "SetBtn", "Set Playable Deck", new Vector2(0.08f, 0.31f), new Vector2(0.5f, 0.43f), new Color(0.55f, 0.35f, 0.05f), 22).onClick).AddListener(new UnityAction(OnSetPlayableDeckClicked));
			_deleteBtn = AnchorButton(parent, "DeleteBtn", "Delete Deck", new Vector2(0.52f, 0.31f), new Vector2(0.92f, 0.43f), new Color(0.55f, 0.12f, 0.12f), 22);
			((UnityEvent)_deleteBtn.onClick).AddListener(new UnityAction(OnDeleteClicked));
			ColorBlock colors = ((Selectable)_deleteBtn).colors;
			((ColorBlock)(ref colors)).disabledColor = new Color(0.28f, 0.28f, 0.32f, 1f);
			((Selectable)_deleteBtn).colors = colors;
			Transform obj = ((Component)_deleteBtn).transform.Find("Label");
			_deleteBtnLabel = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			BuildDeleteModal(parent);
			Vector2 anchorMin2 = new Vector2(0.05f, 0.19f);
			Vector2 anchorMax2 = new Vector2(0.95f, 0.29f);
			bg = new Color(0.05f, 0.05f, 0.08f, 0.8f);
			RectTransform parent2 = UIHelper.CreatePanel((Transform)(object)parent, "ActiveDeckPanel", anchorMin2, anchorMax2, default(Vector2), default(Vector2), bg);
			_activeDeckLabel = UIHelper.CreateText((Transform)(object)parent2, "ActiveDeckLabel", "Active: —", 20, (TextAlignmentOptions)514);
			((UnityEvent)AnchorButton(parent, "CloseBtn", "Close", new Vector2(0.2f, 0.06f), new Vector2(0.8f, 0.16f), new Color(0.45f, 0.1f, 0.1f), 22).onClick).AddListener(new UnityAction(Hide));
			((Component)_canvas).gameObject.SetActive(false);
		}

		private static Button AnchorButton(RectTransform parent, string name, string label, Vector2 anchorMin, Vector2 anchorMax, Color bgColor, int fontSize)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0030: 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_0044: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = anchorMin;
			obj.anchorMax = anchorMax;
			Vector2 offsetMin = (obj.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = bgColor;
			Button obj2 = val.AddComponent<Button>();
			((Selectable)obj2).targetGraphic = (Graphic)(object)val2;
			ColorBlock val3 = default(ColorBlock);
			((ColorBlock)(ref val3)).normalColor = bgColor;
			((ColorBlock)(ref val3)).highlightedColor = bgColor * 1.3f;
			((ColorBlock)(ref val3)).pressedColor = bgColor * 0.7f;
			((ColorBlock)(ref val3)).disabledColor = new Color(0.25f, 0.25f, 0.25f, 0.6f);
			((ColorBlock)(ref val3)).colorMultiplier = 1f;
			((ColorBlock)(ref val3)).fadeDuration = 0.1f;
			ColorBlock colors = val3;
			((Selectable)obj2).colors = colors;
			GameObject val4 = new GameObject("Label");
			val4.transform.SetParent(val.transform, false);
			RectTransform obj3 = val4.AddComponent<RectTransform>();
			obj3.anchorMin = Vector2.zero;
			obj3.anchorMax = Vector2.one;
			offsetMin = (obj3.offsetMax = Vector2.zero);
			obj3.offsetMin = offsetMin;
			TextMeshProUGUI obj4 = val4.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj4).text = label;
			((TMP_Text)obj4).fontSize = fontSize;
			((TMP_Text)obj4).alignment = (TextAlignmentOptions)514;
			((Graphic)obj4).color = Color.white;
			return obj2;
		}

		private TMP_Dropdown BuildDropdown(RectTransform parent, Vector2 anchorMin, Vector2 anchorMax)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_001f: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing r

InfoOverhaul.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using InfoOverhaul.Compat;
using InfoOverhaul.Delta;
using InfoOverhaul.Stats;
using InfoOverhaul.UI;
using Microsoft.CodeAnalysis;
using TMPro;
using UnboundLib.GameModes;
using UnboundLib.Utils;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: AssemblyCompany("InfoOverhaul")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+146ac727a7fc6b83f382d57f53cce40478349c58")]
[assembly: AssemblyProduct("Info Overhaul")]
[assembly: AssemblyTitle("InfoOverhaul")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 InfoOverhaul
{
	internal static class IOLog
	{
		private static ManualLogSource _logger;

		internal static void Init(ManualLogSource logger)
		{
			_logger = logger;
		}

		internal static void Section(string title)
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogInfo((object)("── " + title + " ──"));
			}
		}

		internal static void Line(string message)
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogInfo((object)message);
			}
		}

		internal static void Warn(string message)
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogWarning((object)message);
			}
		}

		internal static void Error(string message)
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogError((object)message);
			}
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("InfoOverhaul", "Info Overhaul", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		private void Awake()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			IOLog.Init(Logger);
			IOLog.Section("Plugin Awake");
			new Harmony("InfoOverhaul").PatchAll();
			StatTemplateDeltaRegistrar.Init();
			MfmTier2Compat.Init();
			((Component)this).gameObject.AddComponent<PickStatsController>();
			((Component)this).gameObject.AddComponent<CardDeltaPreviewOverlay>();
			IOLog.Line("Plugin InfoOverhaul loaded.");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "InfoOverhaul";

		public const string PLUGIN_NAME = "Info Overhaul";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace InfoOverhaul.UI
{
	public class CardDeltaPreviewOverlay : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <OnPickSequenceEnd>d__20 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public CardDeltaPreviewOverlay <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				int num = <>1__state;
				CardDeltaPreviewOverlay cardDeltaPreviewOverlay = <>4__this;
				if (num != 0)
				{
					return false;
				}
				<>1__state = -1;
				cardDeltaPreviewOverlay.OnPickSequenceEnded();
				return false;
			}

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

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

		public static CardDeltaPreviewOverlay instance;

		private static readonly FieldInfo SpawnedCardsField = AccessTools.Field(typeof(CardChoice), "spawnedCards");

		private static readonly FieldInfo SelectedCardField = AccessTools.Field(typeof(CardChoice), "currentlySelectedCard");

		private const int RowsPerCol = 3;

		private const int MaxCols = 5;

		private Canvas _canvas;

		private TextMeshProUGUI _headerText;

		private TextMeshProUGUI[] _colTexts;

		private bool _pickSequenceActive;

		private void Awake()
		{
			instance = this;
			BuildUI();
			GameModeManager.AddHook("PickEnd", (Func<IGameModeHandler, IEnumerator>)OnPickSequenceEnd);
			IOLog.Section("CardDeltaPreviewOverlay initialized");
		}

		private void BuildUI()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			_canvas = UIHelper.CreateFullscreenCanvas("IO_CardDeltaPreview", 55);
			Transform transform = ((Component)_canvas).transform;
			Vector2 anchorMin = new Vector2(0.18f, 0.085f);
			Vector2 anchorMax = new Vector2(0.82f, 0.22f);
			Color? bg = new Color(0.04f, 0.06f, 0.1f, 0.92f);
			RectTransform parent = UIHelper.CreatePanel(transform, "DeltaPanel", anchorMin, anchorMax, default(Vector2), default(Vector2), bg);
			RectTransform parent2 = UIHelper.CreatePanel((Transform)(object)parent, "Header", new Vector2(0.01f, 0.72f), new Vector2(0.99f, 0.98f));
			_headerText = UIHelper.CreateText((Transform)(object)parent2, "HeaderText", "Card preview", 20, (TextAlignmentOptions)4097, (Color?)new Color(0.75f, 0.85f, 1f));
			_colTexts = (TextMeshProUGUI[])(object)new TextMeshProUGUI[5];
			float num = 0.2f;
			for (int i = 0; i < 5; i++)
			{
				float num2 = (float)i * num + 0.01f;
				float num3 = (float)(i + 1) * num - 0.01f;
				RectTransform parent3 = UIHelper.CreatePanel((Transform)(object)parent, $"Col{i}", new Vector2(num2, 0.02f), new Vector2(num3, 0.7f));
				_colTexts[i] = UIHelper.CreateText((Transform)(object)parent3, "Text", string.Empty, 17, (TextAlignmentOptions)257, (Color?)new Color(0.92f, 0.94f, 1f));
				((TMP_Text)_colTexts[i]).richText = true;
			}
			((Component)_canvas).gameObject.SetActive(false);
		}

		public void OnPickSequenceStarted()
		{
			if ((Object)(object)GetLocalHumanPlayer() == (Object)null)
			{
				SetVisible(visible: false);
				return;
			}
			_pickSequenceActive = true;
			SetVisible(visible: true);
			Refresh();
		}

		public void OnPickSequenceEnded()
		{
			_pickSequenceActive = false;
			SetVisible(visible: false);
		}

		private void Update()
		{
			if (_pickSequenceActive && !((Object)(object)_canvas == (Object)null) && ((Component)_canvas).gameObject.activeSelf)
			{
				if (!IsGameActive())
				{
					OnPickSequenceEnded();
				}
				else
				{
					Refresh();
				}
			}
		}

		private static bool IsGameActive()
		{
			if ((Object)(object)GameManager.instance == (Object)null)
			{
				return false;
			}
			if (!GameManager.instance.isPlaying)
			{
				return false;
			}
			if ((Object)(object)PlayerManager.instance == (Object)null)
			{
				return false;
			}
			if (PlayerManager.instance.players == null || PlayerManager.instance.players.Count == 0)
			{
				return false;
			}
			return true;
		}

		private void Refresh()
		{
			Player localHumanPlayer = GetLocalHumanPlayer();
			if ((Object)(object)localHumanPlayer == (Object)null)
			{
				SetVisible(visible: false);
				return;
			}
			if (!TryGetHighlightedCard(out var card))
			{
				((TMP_Text)_headerText).text = "Card preview";
				SetColumns(null);
				((TMP_Text)_colTexts[0]).text = "—";
				return;
			}
			((TMP_Text)_headerText).text = "If selecting " + card.cardName + ":";
			if (!CardDeltaRegistry.TryGetDeltas(localHumanPlayer, card, out var deltas))
			{
				SetColumns(null);
				((TMP_Text)_colTexts[0]).text = "N/A";
			}
			else if (deltas.Count == 0)
			{
				SetColumns(null);
				((TMP_Text)_colTexts[0]).text = "No stat changes";
			}
			else
			{
				SetColumns(deltas);
			}
		}

		private void SetColumns(IReadOnlyList<StatDeltaLine> deltas)
		{
			if (deltas == null)
			{
				for (int i = 0; i < 5; i++)
				{
					((TMP_Text)_colTexts[i]).text = string.Empty;
					((Component)_colTexts[i]).gameObject.SetActive(i == 0);
				}
				return;
			}
			int num = Mathf.Clamp(Mathf.CeilToInt((float)deltas.Count / 3f), 1, 5);
			for (int j = 0; j < 5; j++)
			{
				bool flag = j < num;
				((Component)_colTexts[j]).gameObject.SetActive(flag);
				if (!flag)
				{
					continue;
				}
				StringBuilder stringBuilder = new StringBuilder();
				int num2 = j * 3;
				int num3 = Mathf.Min(num2 + 3, deltas.Count);
				for (int k = num2; k < num3; k++)
				{
					if (k > num2)
					{
						stringBuilder.AppendLine();
					}
					stringBuilder.Append(deltas[k].FormatRichText());
				}
				((TMP_Text)_colTexts[j]).text = stringBuilder.ToString();
			}
		}

		private static bool TryGetHighlightedCard(out CardInfo card)
		{
			card = null;
			CardChoice val = CardChoice.instance;
			if ((Object)(object)val == (Object)null || !val.IsPicking || SpawnedCardsField == null || SelectedCardField == null)
			{
				return false;
			}
			if (!(SpawnedCardsField.GetValue(val) is List<GameObject> list) || list.Count == 0)
			{
				return false;
			}
			int num = (int)SelectedCardField.GetValue(val);
			num = Mathf.Clamp(num, 0, list.Count - 1);
			GameObject val2 = list[num];
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			card = val2.GetComponent<CardInfo>();
			if ((Object)(object)card == (Object)null)
			{
				card = val2.GetComponentInChildren<CardInfo>();
			}
			return (Object)(object)card != (Object)null;
		}

		private static Player GetLocalHumanPlayer()
		{
			if ((Object)(object)PlayerManager.instance == (Object)null)
			{
				return null;
			}
			foreach (Player player in PlayerManager.instance.players)
			{
				if ((Object)(object)player == (Object)null)
				{
					continue;
				}
				PlayerAPI component = ((Component)player).GetComponent<PlayerAPI>();
				if (component == null || !((Behaviour)component).enabled)
				{
					object value = AccessTools.Field(typeof(CharacterData), "view").GetValue(player.data);
					if (value == null)
					{
						return player;
					}
					if ((bool)AccessTools.Property(value.GetType(), "IsMine").GetValue(value, null))
					{
						return player;
					}
				}
			}
			return null;
		}

		private void SetVisible(bool visible)
		{
			if ((Object)(object)_canvas != (Object)null)
			{
				((Component)_canvas).gameObject.SetActive(visible);
			}
		}

		[IteratorStateMachine(typeof(<OnPickSequenceEnd>d__20))]
		private IEnumerator OnPickSequenceEnd(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnPickSequenceEnd>d__20(0)
			{
				<>4__this = this
			};
		}
	}
	public class PickStatsController : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <OnPickSequenceEnd>d__14 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public PickStatsController <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				int num = <>1__state;
				PickStatsController pickStatsController = <>4__this;
				if (num != 0)
				{
					return false;
				}
				<>1__state = -1;
				IOLog.Line("Pick sequence ended — auto-closing stats window.");
				pickStatsController.EndPickPhase("HookPickEnd");
				return false;
			}

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

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

		[CompilerGenerated]
		private sealed class <OnPlayerPickEnd>d__13 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

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

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

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

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

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				IOLog.Line($"Single player pick ended (picker={currentPickerID}); keeping stats UI up until pick sequence ends.");
				return false;
			}

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

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

		public static PickStatsController instance;

		public static bool isPickPhase;

		public static int currentPickerID = -1;

		private Canvas _canvas;

		private StatsPopup _popup;

		private GameObject _showStatsBtnGo;

		private void Awake()
		{
			instance = this;
			BuildUI();
			GameModeManager.AddHook("PlayerPickEnd", (Func<IGameModeHandler, IEnumerator>)OnPlayerPickEnd);
			GameModeManager.AddHook("PickEnd", (Func<IGameModeHandler, IEnumerator>)OnPickSequenceEnd);
			IOLog.Section("PickStatsController initialized");
		}

		private void BuildUI()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			_canvas = UIHelper.CreateFullscreenCanvas("IO_PickStatsCanvas", 160);
			RectTransform component = ((Component)_canvas).GetComponent<RectTransform>();
			Button val = UIHelper.AnchorButton(component, "ShowStatsBtn", "Show Stats", new Vector2(0.02f, 0.02f), new Vector2(0.16f, 0.08f), new Color(0.18f, 0.35f, 0.55f, 1f), 24);
			((UnityEvent)val.onClick).AddListener(new UnityAction(TogglePopup));
			_showStatsBtnGo = ((Component)val).gameObject;
			_popup = StatsPopup.Create((Transform)(object)component);
			((Component)_canvas).gameObject.SetActive(false);
		}

		public void BeginPickPhase(int pickerID, string source)
		{
			if (pickerID >= 0)
			{
				if ((Object)(object)GetLocalHumanPlayer() == (Object)null)
				{
					HideAll();
					IOLog.Line($"Pick phase for player {pickerID} (source={source}) — no local human, UI hidden.");
					return;
				}
				currentPickerID = pickerID;
				isPickPhase = true;
				((Component)_canvas).gameObject.SetActive(true);
				_showStatsBtnGo.SetActive(true);
				CardDeltaPreviewOverlay.instance?.OnPickSequenceStarted();
				IOLog.Line($"Pick phase active — picker={pickerID}, showing local stats (source={source}).");
			}
		}

		public void EndPickPhase(string source)
		{
			IOLog.Line($"Pick phase ended (source={source}), was picker={currentPickerID}");
			isPickPhase = false;
			currentPickerID = -1;
			CardDeltaPreviewOverlay.instance?.OnPickSequenceEnded();
			HideAll();
		}

		private void HideAll()
		{
			_popup?.Hide();
			if ((Object)(object)_canvas != (Object)null)
			{
				((Component)_canvas).gameObject.SetActive(false);
			}
		}

		private void TogglePopup()
		{
			Player localHumanPlayer = GetLocalHumanPlayer();
			if (!((Object)(object)localHumanPlayer == (Object)null))
			{
				if (_popup.IsVisible)
				{
					_popup.Hide();
				}
				else
				{
					_popup.Show(localHumanPlayer);
				}
			}
		}

		private static Player GetLocalHumanPlayer()
		{
			if ((Object)(object)PlayerManager.instance == (Object)null)
			{
				return null;
			}
			foreach (Player player in PlayerManager.instance.players)
			{
				if ((Object)(object)player == (Object)null)
				{
					continue;
				}
				PlayerAPI component = ((Component)player).GetComponent<PlayerAPI>();
				if (component == null || !((Behaviour)component).enabled)
				{
					object value = AccessTools.Field(typeof(CharacterData), "view").GetValue(player.data);
					if (value == null)
					{
						return player;
					}
					if ((bool)AccessTools.Property(value.GetType(), "IsMine").GetValue(value, null))
					{
						return player;
					}
				}
			}
			return null;
		}

		[IteratorStateMachine(typeof(<OnPlayerPickEnd>d__13))]
		private IEnumerator OnPlayerPickEnd(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnPlayerPickEnd>d__13(0);
		}

		[IteratorStateMachine(typeof(<OnPickSequenceEnd>d__14))]
		private IEnumerator OnPickSequenceEnd(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnPickSequenceEnd>d__14(0)
			{
				<>4__this = this
			};
		}

		private void Update()
		{
			if ((Object)(object)_canvas != (Object)null && ((Component)_canvas).gameObject.activeSelf && !IsGameActive())
			{
				IOLog.Line("PickStatsController — game no longer active, hiding UI.");
				EndPickPhase("GameEnded");
			}
		}

		private static bool IsGameActive()
		{
			if ((Object)(object)GameManager.instance == (Object)null)
			{
				return false;
			}
			if (!GameManager.instance.isPlaying)
			{
				return false;
			}
			if ((Object)(object)PlayerManager.instance == (Object)null)
			{
				return false;
			}
			if (PlayerManager.instance.players == null || PlayerManager.instance.players.Count == 0)
			{
				return false;
			}
			return true;
		}
	}
	internal class StatsPopup : MonoBehaviour
	{
		private readonly List<TextMeshProUGUI> _leftLines = new List<TextMeshProUGUI>();

		private readonly List<TextMeshProUGUI> _rightLines = new List<TextMeshProUGUI>();

		private RectTransform _root;

		private Player _player;

		public bool IsVisible => ((Component)this).gameObject.activeSelf;

		public static StatsPopup Create(Transform parent)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("IO_StatsPopup");
			val.transform.SetParent(parent, false);
			StatsPopup statsPopup = val.AddComponent<StatsPopup>();
			statsPopup.Build();
			val.SetActive(false);
			return statsPopup;
		}

		private void Build()
		{
			//IL_0017: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00e1: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Expected O, but got Unknown
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			_root = ((Component)this).gameObject.AddComponent<RectTransform>();
			_root.anchorMin = Vector2.zero;
			_root.anchorMax = Vector2.one;
			RectTransform root = _root;
			Vector2 offsetMin = (_root.offsetMax = Vector2.zero);
			root.offsetMin = offsetMin;
			GameObject val = new GameObject("Backdrop");
			val.transform.SetParent(((Component)this).transform, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			offsetMin = (obj.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			((Graphic)val.AddComponent<Image>()).color = new Color(0.02f, 0.02f, 0.05f, 1f);
			Transform transform = ((Component)this).transform;
			Vector2 anchorMin = new Vector2(0.12f, 0.08f);
			Vector2 anchorMax = new Vector2(0.88f, 0.92f);
			Color? bg = new Color(0.08f, 0.09f, 0.14f, 1f);
			RectTransform parent = UIHelper.CreatePanel(transform, "Panel", anchorMin, anchorMax, default(Vector2), default(Vector2), bg);
			UIHelper.CreateText((Transform)(object)UIHelper.CreatePanel((Transform)(object)parent, "Title", new Vector2(0f, 0.9f), Vector2.one), "TitleText", "Player Stats", 36, (TextAlignmentOptions)514);
			((UnityEvent)UIHelper.AnchorButton(parent, "CloseBtn", "Close", new Vector2(0.82f, 0.91f), new Vector2(0.98f, 0.99f), new Color(0.45f, 0.12f, 0.12f), 22).onClick).AddListener(new UnityAction(Hide));
			RectTransform parent2 = UIHelper.CreatePanel((Transform)(object)parent, "Columns", new Vector2(0.04f, 0.04f), new Vector2(0.96f, 0.88f));
			RectTransform parent3 = UIHelper.CreatePanel((Transform)(object)parent2, "LeftColumn", new Vector2(0f, 0f), new Vector2(0.48f, 1f));
			RectTransform parent4 = UIHelper.CreatePanel((Transform)(object)parent2, "RightColumn", new Vector2(0.52f, 0f), Vector2.one);
			BuildColumn(parent3, _leftLines, 12);
			BuildColumn(parent4, _rightLines, 12);
		}

		private static void BuildColumn(RectTransform parent, List<TextMeshProUGUI> sink, int lineCount)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f / (float)lineCount;
			for (int i = 0; i < lineCount; i++)
			{
				float num2 = 1f - (float)i * num;
				float num3 = num2 - num;
				TextMeshProUGUI item = UIHelper.CreateText((Transform)(object)UIHelper.CreatePanel((Transform)(object)parent, $"Line{i}", new Vector2(0f, num3), new Vector2(1f, num2)), "Text", "—", 22, (TextAlignmentOptions)4097, (Color?)new Color(0.92f, 0.94f, 1f));
				sink.Add(item);
			}
		}

		public void Show(Player player)
		{
			_player = player;
			((Component)this).gameObject.SetActive(true);
			Refresh();
		}

		public void Hide()
		{
			((Component)this).gameObject.SetActive(false);
			_player = null;
		}

		private void Update()
		{
			if (IsVisible && !((Object)(object)_player == (Object)null))
			{
				Refresh();
			}
		}

		private void Refresh()
		{
			List<StatsReader.StatLine> stats = StatsReader.Collect(_player);
			ApplyColumn(_leftLines, stats, 0);
			ApplyColumn(_rightLines, stats, _leftLines.Count);
		}

		private static void ApplyColumn(List<TextMeshProUGUI> labels, List<StatsReader.StatLine> stats, int offset)
		{
			for (int i = 0; i < labels.Count; i++)
			{
				int num = offset + i;
				((TMP_Text)labels[i]).text = ((num < stats.Count) ? stats[num].Text : string.Empty);
			}
		}
	}
	internal static class UIHelper
	{
		public static Canvas CreateFullscreenCanvas(string name, int sortOrder = 100)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_000c: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			Object.DontDestroyOnLoad((Object)val);
			val.SetActive(false);
			Canvas val2 = val.AddComponent<Canvas>();
			val2.renderMode = (RenderMode)0;
			val2.sortingOrder = sortOrder;
			CanvasScaler obj = val.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)1;
			obj.referenceResolution = new Vector2(1920f, 1080f);
			val.AddComponent<GraphicRaycaster>();
			return val2;
		}

		public static RectTransform CreatePanel(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin = default(Vector2), Vector2 offsetMax = default(Vector2), Color? bg = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = anchorMin;
			obj.anchorMax = anchorMax;
			obj.offsetMin = offsetMin;
			obj.offsetMax = offsetMax;
			if (bg.HasValue)
			{
				((Graphic)val.AddComponent<Image>()).color = bg.Value;
			}
			return obj;
		}

		public static TextMeshProUGUI CreateText(Transform parent, string name, string text, int fontSize = 24, TextAlignmentOptions alignment = 514, Color? color = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			obj.offsetMin = Vector2.zero;
			obj.offsetMax = Vector2.zero;
			TextMeshProUGUI obj2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj2).text = text;
			((TMP_Text)obj2).fontSize = fontSize;
			((TMP_Text)obj2).alignment = alignment;
			((Graphic)obj2).color = (Color)(((??)color) ?? Color.white);
			return obj2;
		}

		public static Button AnchorButton(RectTransform parent, string name, string label, Vector2 anchorMin, Vector2 anchorMax, Color bgColor, int fontSize)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0030: 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_0044: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = anchorMin;
			obj.anchorMax = anchorMax;
			Vector2 offsetMin = (obj.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = bgColor;
			Button obj2 = val.AddComponent<Button>();
			((Selectable)obj2).targetGraphic = (Graphic)(object)val2;
			ColorBlock val3 = default(ColorBlock);
			((ColorBlock)(ref val3)).normalColor = bgColor;
			((ColorBlock)(ref val3)).highlightedColor = bgColor * 1.3f;
			((ColorBlock)(ref val3)).pressedColor = bgColor * 0.7f;
			((ColorBlock)(ref val3)).disabledColor = new Color(0.25f, 0.25f, 0.25f, 0.6f);
			((ColorBlock)(ref val3)).colorMultiplier = 1f;
			((ColorBlock)(ref val3)).fadeDuration = 0.1f;
			ColorBlock colors = val3;
			((Selectable)obj2).colors = colors;
			GameObject val4 = new GameObject("Label");
			val4.transform.SetParent(val.transform, false);
			RectTransform obj3 = val4.AddComponent<RectTransform>();
			obj3.anchorMin = Vector2.zero;
			obj3.anchorMax = Vector2.one;
			offsetMin = (obj3.offsetMax = Vector2.zero);
			obj3.offsetMin = offsetMin;
			TextMeshProUGUI obj4 = val4.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj4).text = label;
			((TMP_Text)obj4).fontSize = fontSize;
			((TMP_Text)obj4).alignment = (TextAlignmentOptions)514;
			((Graphic)obj4).color = Color.white;
			return obj2;
		}
	}
}
namespace InfoOverhaul.Stats
{
	internal static class LifestealResistanceStatsBridge
	{
		private static bool _resolved;

		private static FieldInfo _instanceField;

		private static MethodInfo _getPercent;

		public static bool IsAvailable
		{
			get
			{
				Resolve();
				if (_instanceField != null)
				{
					return _getPercent != null;
				}
				return false;
			}
		}

		private static void Resolve()
		{
			if (_resolved)
			{
				return;
			}
			_resolved = true;
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ShieldsMod");
				if (!(assembly == null))
				{
					Type type = assembly.GetType("ShieldsMod.Lifesteal.LifestealResistanceManager");
					if (!(type == null))
					{
						_instanceField = type.GetField("instance", BindingFlags.Static | BindingFlags.Public);
						_getPercent = type.GetMethod("GetReductionPercent", BindingFlags.Instance | BindingFlags.Public);
					}
				}
			}
			catch (Exception ex)
			{
				IOLog.Warn("LifestealResistanceStatsBridge resolve failed: " + ex.Message);
			}
		}

		public static bool TryGetPercent(int playerID, out float percent)
		{
			percent = 0f;
			Resolve();
			if (_instanceField == null || _getPercent == null)
			{
				return false;
			}
			try
			{
				object value = _instanceField.GetValue(null);
				if (value == null)
				{
					return false;
				}
				percent = (float)_getPercent.Invoke(value, new object[1] { playerID });
				return true;
			}
			catch (Exception ex)
			{
				IOLog.Warn("TryGetPercent failed: " + ex.Message);
				return false;
			}
		}
	}
	internal static class PoisonResistanceStatsBridge
	{
		private static bool _resolved;

		private static FieldInfo _instanceField;

		private static MethodInfo _getPercent;

		public static bool IsAvailable
		{
			get
			{
				Resolve();
				if (_instanceField != null)
				{
					return _getPercent != null;
				}
				return false;
			}
		}

		private static void Resolve()
		{
			if (_resolved)
			{
				return;
			}
			_resolved = true;
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ShieldsMod");
				if (!(assembly == null))
				{
					Type type = assembly.GetType("ShieldsMod.Poison.PoisonResistanceManager");
					if (!(type == null))
					{
						_instanceField = type.GetField("instance", BindingFlags.Static | BindingFlags.Public);
						_getPercent = type.GetMethod("GetReductionPercent", BindingFlags.Instance | BindingFlags.Public);
					}
				}
			}
			catch (Exception ex)
			{
				IOLog.Warn("PoisonResistanceStatsBridge resolve failed: " + ex.Message);
			}
		}

		public static bool TryGetPercent(int playerID, out float percent)
		{
			percent = 0f;
			Resolve();
			if (_instanceField == null || _getPercent == null)
			{
				return false;
			}
			try
			{
				object value = _instanceField.GetValue(null);
				if (value == null)
				{
					return false;
				}
				percent = (float)_getPercent.Invoke(value, new object[1] { playerID });
				return true;
			}
			catch (Exception ex)
			{
				IOLog.Warn("TryGetPercent failed: " + ex.Message);
				return false;
			}
		}
	}
	internal static class ShieldStatsBridge
	{
		private static bool _resolved;

		private static FieldInfo _instanceField;

		private static MethodInfo _getShield;

		private static FieldInfo _currentField;

		private static FieldInfo _maxField;

		public static bool IsAvailable
		{
			get
			{
				Resolve();
				if (_instanceField != null)
				{
					return _getShield != null;
				}
				return false;
			}
		}

		private static void Resolve()
		{
			if (_resolved)
			{
				return;
			}
			_resolved = true;
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ShieldsMod");
				if (assembly == null)
				{
					IOLog.Line("ShieldsMod not loaded — Shield Health will show as N/A.");
					return;
				}
				Type type = assembly.GetType("ShieldsMod.Shield.ShieldManager");
				Type type2 = assembly.GetType("ShieldsMod.Shield.ShieldState");
				if (type == null || type2 == null)
				{
					IOLog.Warn("ShieldsMod shield types not found.");
					return;
				}
				_instanceField = type.GetField("instance", BindingFlags.Static | BindingFlags.Public);
				_getShield = type.GetMethod("GetShield", BindingFlags.Instance | BindingFlags.Public);
				_currentField = type2.GetField("Current", BindingFlags.Instance | BindingFlags.Public);
				_maxField = type2.GetField("Max", BindingFlags.Instance | BindingFlags.Public);
				if (_instanceField == null || _getShield == null || _currentField == null || _maxField == null)
				{
					IOLog.Warn("ShieldsMod shield API incomplete.");
				}
			}
			catch (Exception ex)
			{
				IOLog.Error("ShieldStatsBridge resolve failed: " + ex.Message);
			}
		}

		public static bool TryGetShieldHealth(int playerID, out float current, out float max)
		{
			current = 0f;
			max = 0f;
			Resolve();
			if (_instanceField == null || _getShield == null)
			{
				return false;
			}
			try
			{
				object value = _instanceField.GetValue(null);
				if (value == null)
				{
					return false;
				}
				object obj = _getShield.Invoke(value, new object[1] { playerID });
				if (obj == null)
				{
					return false;
				}
				current = (float)_currentField.GetValue(obj);
				max = (float)_maxField.GetValue(obj);
				return true;
			}
			catch (Exception ex)
			{
				IOLog.Warn("TryGetShieldHealth failed: " + ex.Message);
				return false;
			}
		}
	}
	internal static class StatsReader
	{
		internal readonly struct StatLine
		{
			public readonly string Text;

			public StatLine(string text)
			{
				Text = text;
			}
		}

		public static List<StatLine> Collect(Player player)
		{
			List<StatLine> list = new List<StatLine>(24);
			if ((Object)(object)player == (Object)null)
			{
				return list;
			}
			Gun val = player.data?.weaponHandler?.gun;
			Block val2 = player.data?.block;
			list.Add(new StatLine($"HP: {player.data.health:f0} / {player.data.maxHealth:f0}"));
			list.Add(new StatLine($"Lives: {player.data.stats.respawns + 1:f0}"));
			list.Add(new StatLine(((Object)(object)val2 != (Object)null) ? $"Block CD: {val2.Cooldown():f2}s" : "Block CD: —"));
			list.Add(new StatLine(((Object)(object)val2 != (Object)null) ? $"Block Count: {val2.additionalBlocks + 1:f0}" : "Block Count: —"));
			list.Add(new StatLine(FormatShieldHealth(player.playerID)));
			list.Add(new StatLine(FormatPoisonResistance(player.playerID)));
			list.Add(new StatLine(FormatStunResistance(player.playerID)));
			list.Add(new StatLine(FormatLifestealResistance(player.playerID)));
			if ((Object)(object)val != (Object)null)
			{
				list.Add(new StatLine($"DMG: {val.damage * 55f * val.bulletDamageMultiplier:f0}"));
				list.Add(new StatLine($"Knockback: {val.knockback:f2}"));
				list.Add(new StatLine($"Life Steal: {player.data.stats.lifeSteal:f2}"));
				list.Add(new StatLine($"Damage Grow: {val.damageAfterDistanceMultiplier:f2}"));
				list.Add(new StatLine($"Bullet Slow: {val.slow:f2}"));
				list.Add(new StatLine($"Move SPD: {player.data.stats.movementSpeed:f2}"));
				list.Add(new StatLine($"Jump Height: {player.data.stats.jump:f2}"));
				list.Add(new StatLine($"Player Size: {player.data.stats.sizeMultiplier:f2}"));
				list.Add(new StatLine($"Attack SPD: {val.attackSpeed * val.attackSpeedMultiplier:f2}s"));
				list.Add(new StatLine($"Bullet SPD: {val.projectileSpeed:f2}"));
				list.Add(new StatLine($"Projectile SPD: {val.projectielSimulatonSpeed:f2}"));
				GunAmmo componentInChildren = ((Component)val).GetComponentInChildren<GunAmmo>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					float num = (componentInChildren.reloadTime + componentInChildren.reloadTimeAdd) * componentInChildren.reloadTimeMultiplier;
					list.Add(new StatLine($"Reload Time: {num:f2}s"));
					list.Add(new StatLine($"Ammo: {componentInChildren.maxAmmo:f0}"));
				}
				else
				{
					list.Add(new StatLine("Reload Time: —"));
					list.Add(new StatLine("Ammo: —"));
				}
				list.Add(new StatLine($"Bullet Gravity: {val.gravity:f2}"));
				list.Add(new StatLine($"Bullets: {val.numberOfProjectiles:f0}"));
				list.Add(new StatLine($"Bullet Range: {val.destroyBulletAfter:f2}"));
				list.Add(new StatLine($"Bounces: {val.reflects:f0}"));
				list.Add(new StatLine($"Bursts: {val.bursts:f0}"));
			}
			else
			{
				list.Add(new StatLine("DMG: —"));
				list.Add(new StatLine("Knockback: —"));
				list.Add(new StatLine($"Life Steal: {player.data.stats.lifeSteal:f2}"));
				list.Add(new StatLine("Damage Grow: —"));
				list.Add(new StatLine("Bullet Slow: —"));
				list.Add(new StatLine($"Move SPD: {player.data.stats.movementSpeed:f2}"));
				list.Add(new StatLine($"Jump Height: {player.data.stats.jump:f2}"));
				list.Add(new StatLine($"Player Size: {player.data.stats.sizeMultiplier:f2}"));
				list.Add(new StatLine("Attack SPD: —"));
				list.Add(new StatLine("Bullet SPD: —"));
				list.Add(new StatLine("Projectile SPD: —"));
				list.Add(new StatLine("Reload Time: —"));
				list.Add(new StatLine("Ammo: —"));
				list.Add(new StatLine("Bullet Gravity: —"));
				list.Add(new StatLine("Bullets: —"));
				list.Add(new StatLine("Bullet Range: —"));
				list.Add(new StatLine("Bounces: —"));
				list.Add(new StatLine("Bursts: —"));
			}
			return list;
		}

		private static string FormatShieldHealth(int playerID)
		{
			if (ShieldStatsBridge.TryGetShieldHealth(playerID, out var current, out var max))
			{
				if (!(max > 0f))
				{
					return "Shield Health: None";
				}
				return $"Shield Health: {current:f0} / {max:f0}";
			}
			if (!ShieldStatsBridge.IsAvailable)
			{
				return "Shield Health: N/A";
			}
			return "Shield Health: — / —";
		}

		private static string FormatPoisonResistance(int playerID)
		{
			if (PoisonResistanceStatsBridge.TryGetPercent(playerID, out var percent))
			{
				return $"Poison Resistance: {percent:f0}%";
			}
			if (!PoisonResistanceStatsBridge.IsAvailable)
			{
				return "Poison Resistance: N/A";
			}
			return "Poison Resistance: 0%";
		}

		private static string FormatStunResistance(int playerID)
		{
			if (StunResistanceStatsBridge.TryGetPercent(playerID, out var percent))
			{
				return $"Stun Resistance: {percent:f0}%";
			}
			if (!StunResistanceStatsBridge.IsAvailable)
			{
				return "Stun Resistance: N/A";
			}
			return "Stun Resistance: 0%";
		}

		private static string FormatLifestealResistance(int playerID)
		{
			if (LifestealResistanceStatsBridge.TryGetPercent(playerID, out var percent))
			{
				return $"Lifesteal Resistance: {percent:f0}%";
			}
			if (!LifestealResistanceStatsBridge.IsAvailable)
			{
				return "Lifesteal Resistance: N/A";
			}
			return "Lifesteal Resistance: 0%";
		}
	}
	internal static class StunResistanceStatsBridge
	{
		private static bool _resolved;

		private static FieldInfo _instanceField;

		private static MethodInfo _getPercent;

		public static bool IsAvailable
		{
			get
			{
				Resolve();
				if (_instanceField != null)
				{
					return _getPercent != null;
				}
				return false;
			}
		}

		private static void Resolve()
		{
			if (_resolved)
			{
				return;
			}
			_resolved = true;
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ShieldsMod");
				if (!(assembly == null))
				{
					Type type = assembly.GetType("ShieldsMod.Stun.StunResistanceManager");
					if (!(type == null))
					{
						_instanceField = type.GetField("instance", BindingFlags.Static | BindingFlags.Public);
						_getPercent = type.GetMethod("GetReductionPercent", BindingFlags.Instance | BindingFlags.Public);
					}
				}
			}
			catch (Exception ex)
			{
				IOLog.Warn("StunResistanceStatsBridge resolve failed: " + ex.Message);
			}
		}

		public static bool TryGetPercent(int playerID, out float percent)
		{
			percent = 0f;
			Resolve();
			if (_instanceField == null || _getPercent == null)
			{
				return false;
			}
			try
			{
				object value = _instanceField.GetValue(null);
				if (value == null)
				{
					return false;
				}
				percent = (float)_getPercent.Invoke(value, new object[1] { playerID });
				return true;
			}
			catch (Exception ex)
			{
				IOLog.Warn("TryGetPercent failed: " + ex.Message);
				return false;
			}
		}
	}
}
namespace InfoOverhaul.Patches
{
	[HarmonyPatch]
	internal static class PickPhasePatches
	{
		[HarmonyPatch(typeof(CardChoiceVisuals), "Show")]
		[HarmonyPrefix]
		private static void CardChoiceVisuals_Show_Prefix(int pickerID, bool animateIn)
		{
			PickStatsController.instance?.BeginPickPhase(pickerID, "CardChoiceVisuals.Show");
		}

		[HarmonyPatch(typeof(CardChoice), "StartPick")]
		[HarmonyPostfix]
		private static void CardChoice_StartPick_Postfix(int picksToSet, int pickerIDToSet)
		{
			PickStatsController.instance?.BeginPickPhase(pickerIDToSet, "CardChoice.StartPick");
		}
	}
}
namespace InfoOverhaul.Delta
{
	public static class CardDeltaRegistry
	{
		public delegate IReadOnlyList<StatDeltaLine> DeltaProvider(Player player, CardInfo card);

		public delegate IReadOnlyList<(string label, string before, string after)> SimpleDeltaProvider(Player player, CardInfo card);

		private static readonly Dictionary<string, DeltaProvider> Providers = new Dictionary<string, DeltaProvider>(StringComparer.Ordinal);

		private static readonly Dictionary<string, List<DeltaProvider>> Addons = new Dictionary<string, List<DeltaProvider>>(StringComparer.Ordinal);

		private static readonly Dictionary<string, DeltaProvider> RemovalProviders = new Dictionary<string, DeltaProvider>(StringComparer.Ordinal);

		public static void RegisterSimple(string cardName, SimpleDeltaProvider provider)
		{
			Register(cardName, (Player player, CardInfo card) => ToLines(provider(player, card)));
		}

		public static void Register(string cardName, DeltaProvider provider)
		{
			if (!string.IsNullOrEmpty(cardName) && provider != null)
			{
				Providers[cardName] = provider;
				IOLog.Line("CardDeltaRegistry — registered '" + cardName + "'.");
			}
		}

		public static void RegisterAddon(string cardName, DeltaProvider addon)
		{
			if (!string.IsNullOrEmpty(cardName) && addon != null)
			{
				if (!Addons.TryGetValue(cardName, out var value))
				{
					value = new List<DeltaProvider>();
					Addons[cardName] = value;
				}
				value.Add(addon);
				IOLog.Line("CardDeltaRegistry — addon registered for '" + cardName + "'.");
			}
		}

		public static void RegisterAddonSimple(string cardName, SimpleDeltaProvider addon)
		{
			RegisterAddon(cardName, (Player player, CardInfo card) => ToLines(addon(player, card)));
		}

		public static void RegisterRemovalSimple(string cardName, SimpleDeltaProvider provider)
		{
			RegisterRemoval(cardName, (Player player, CardInfo card) => ToLines(provider(player, card)));
		}

		public static void RegisterRemoval(string cardName, DeltaProvider provider)
		{
			if (!string.IsNullOrEmpty(cardName) && provider != null)
			{
				RemovalProviders[cardName] = provider;
				IOLog.Line("CardDeltaRegistry — removal registered '" + cardName + "'.");
			}
		}

		public static bool IsRegistered(string cardName)
		{
			if (!string.IsNullOrEmpty(cardName))
			{
				if (!Providers.ContainsKey(cardName))
				{
					if (Addons.TryGetValue(cardName, out var value))
					{
						return value.Count > 0;
					}
					return false;
				}
				return true;
			}
			return false;
		}

		public static bool TryGetDeltas(Player player, CardInfo card, out IReadOnlyList<StatDeltaLine> deltas)
		{
			deltas = null;
			if ((Object)(object)player == (Object)null || (Object)(object)card == (Object)null)
			{
				return false;
			}
			string text = ResolveCardName(card);
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			DeltaProvider value;
			bool flag = Providers.TryGetValue(text, out value);
			List<DeltaProvider> value2;
			bool flag2 = Addons.TryGetValue(text, out value2) && value2.Count > 0;
			if (!flag && !flag2)
			{
				return false;
			}
			List<StatDeltaLine> list = new List<StatDeltaLine>();
			if (flag)
			{
				list.AddRange(value(player, card) ?? Array.Empty<StatDeltaLine>());
			}
			if (flag2)
			{
				foreach (DeltaProvider item in value2)
				{
					list.AddRange(item(player, card) ?? Array.Empty<StatDeltaLine>());
				}
			}
			deltas = list;
			return true;
		}

		public static bool TryGetRemovalDeltas(Player player, CardInfo card, out IReadOnlyList<StatDeltaLine> deltas)
		{
			deltas = null;
			if ((Object)(object)player == (Object)null || (Object)(object)card == (Object)null)
			{
				return false;
			}
			string text = ResolveCardName(card);
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			if (RemovalProviders.TryGetValue(text, out var value))
			{
				deltas = value(player, card) ?? Array.Empty<StatDeltaLine>();
				return true;
			}
			IReadOnlyList<StatDeltaLine> readOnlyList = StatTemplateDeltaProvider.ComputeRemoval(player, card);
			if (readOnlyList.Count > 0)
			{
				deltas = readOnlyList;
				return true;
			}
			if (!TryGetDeltas(player, card, out var deltas2) || deltas2.Count == 0)
			{
				return false;
			}
			deltas = deltas2.Select((StatDeltaLine line) => line.Inverted).ToList();
			return true;
		}

		internal static string ResolveCardName(CardInfo card)
		{
			if (!string.IsNullOrEmpty(card.cardName))
			{
				return card.cardName;
			}
			if (!((Object)(object)card.sourceCard != (Object)null))
			{
				return null;
			}
			return card.sourceCard.cardName;
		}

		private static IReadOnlyList<StatDeltaLine> ToLines(IReadOnlyList<(string label, string before, string after)> tuples)
		{
			if (tuples == null || tuples.Count == 0)
			{
				return Array.Empty<StatDeltaLine>();
			}
			return tuples.Select(((string label, string before, string after) t) => (string.IsNullOrEmpty(t.before) && string.IsNullOrEmpty(t.after)) ? StatDeltaLine.Note(t.label) : new StatDeltaLine(t.label, t.before, t.after)).ToList();
		}
	}
	public static class CardDeltaTier2
	{
		public static void RegisterEffectNotes(string cardName, params string[] notes)
		{
			if (notes != null && notes.Length != 0)
			{
				CardDeltaRegistry.RegisterAddon(cardName, (Player _, CardInfo __) => notes.Select(StatDeltaLine.Note).ToList());
			}
		}

		public static void RegisterEffectNotes(string cardName, Func<Player, CardInfo, IReadOnlyList<string>> notes)
		{
			if (notes != null)
			{
				CardDeltaRegistry.RegisterAddon(cardName, (Player player, CardInfo card) => (notes(player, card) ?? Array.Empty<string>()).Select(StatDeltaLine.Note).ToList());
			}
		}

		public static void RegisterOverrideSimple(string cardName, CardDeltaRegistry.SimpleDeltaProvider provider)
		{
			CardDeltaRegistry.RegisterSimple(cardName, provider);
		}
	}
	public readonly struct StatDeltaLine
	{
		private const string IncreaseColor = "#66FF88";

		private const string DecreaseColor = "#FF6666";

		private const string NeutralColor = "#EBF0FF";

		private static readonly HashSet<string> LowerIsBetterStats = new HashSet<string> { "Block CD", "Player Size", "Attack SPD", "Reload Time", "Bullet Gravity" };

		public readonly string Label;

		public readonly string Before;

		public readonly string After;

		public readonly bool IsNote;

		public StatDeltaLine Inverted
		{
			get
			{
				if (!IsNote)
				{
					return new StatDeltaLine(Label, After, Before);
				}
				return this;
			}
		}

		public StatDeltaLine(string label, string before, string after, bool isNote = false)
		{
			Label = label;
			Before = before;
			After = after;
			IsNote = isNote;
		}

		public static StatDeltaLine Note(string text)
		{
			return new StatDeltaLine(text, null, null, isNote: true);
		}

		public string Format()
		{
			if (!IsNote)
			{
				return Label + ": " + Before + " --> " + After;
			}
			return Label;
		}

		public string FormatRichText()
		{
			if (IsNote)
			{
				return Label;
			}
			if (!TryParseStatValue(Before, out var value) || !TryParseStatValue(After, out var value2))
			{
				return Format();
			}
			bool num = LowerIsBetterStats.Contains(Label);
			bool flag = value2 > value;
			bool flag2 = (num ? (!flag) : flag);
			string text = ((value2 == value) ? "#EBF0FF" : (flag2 ? "#66FF88" : "#FF6666"));
			return Label + ": " + Before + " --> <color=" + text + ">" + After + "</color>";
		}

		private static bool TryParseStatValue(string text, out float value)
		{
			value = 0f;
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			int i;
			for (i = 0; i < text.Length && (char.IsDigit(text[i]) || text[i] == '.' || text[i] == '-'); i++)
			{
			}
			if (i == 0)
			{
				return false;
			}
			return float.TryParse(text.Substring(0, i), NumberStyles.Float, CultureInfo.InvariantCulture, out value);
		}
	}
	internal static class StatTemplateDeltaProvider
	{
		private const float Epsilon = 0.0001f;

		public static IReadOnlyList<StatDeltaLine> Compute(Player player, CardInfo card)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)card == (Object)null)
			{
				return Array.Empty<StatDeltaLine>();
			}
			GameObject obj = (((Object)(object)card.sourceCard != (Object)null) ? ((Component)card.sourceCard).gameObject : ((Component)card).gameObject);
			Gun component = obj.GetComponent<Gun>();
			CharacterStatModifiers component2 = obj.GetComponent<CharacterStatModifiers>();
			Block componentInChildren = obj.GetComponentInChildren<Block>();
			if (!HasStatTemplate(component, component2, componentInChildren))
			{
				return Array.Empty<StatDeltaLine>();
			}
			Gun val = player.data?.weaponHandler?.gun;
			Block val2 = player.data?.block;
			CharacterData data = player.data;
			CharacterStatModifiers component3 = ((Component)player).GetComponent<CharacterStatModifiers>();
			GunAmmo val3 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInChildren<GunAmmo>() : null);
			List<StatDeltaLine> list = new List<StatDeltaLine>();
			if ((Object)(object)component2 != (Object)null && (Object)(object)data != (Object)null && (Object)(object)component3 != (Object)null)
			{
				TryAdd(list, "HP", data.maxHealth, data.maxHealth * component2.health, "f0");
				TryAdd(list, "Lives", (float)component3.respawns + 1f, (float)(component3.respawns + component2.respawns) + 1f, "f0");
				TryAdd(list, "Move SPD", component3.movementSpeed, component3.movementSpeed * component2.movementSpeed, "f2");
				TryAdd(list, "Jump Height", component3.jump, component3.jump * component2.jump, "f2");
				TryAdd(list, "Player Size", component3.sizeMultiplier, component3.sizeMultiplier * component2.sizeMultiplier, "f2");
				TryAdd(list, "Life Steal", component3.lifeSteal, component3.lifeSteal + component2.lifeSteal, "f2");
			}
			if ((Object)(object)componentInChildren != (Object)null && (Object)(object)val2 != (Object)null)
			{
				float before = val2.Cooldown();
				float after = (val2.cooldown + val2.cdAdd + componentInChildren.cdAdd) * (val2.cdMultiplier * componentInChildren.cdMultiplier);
				TryAdd(list, "Block CD", before, after, "f2", "s");
				TryAdd(list, "Block Count", (float)val2.additionalBlocks + 1f, (float)(val2.additionalBlocks + componentInChildren.additionalBlocks) + 1f, "f0");
			}
			if ((Object)(object)component != (Object)null && (Object)(object)val != (Object)null)
			{
				float before2 = val.damage * 55f * val.bulletDamageMultiplier;
				float after2 = ApplyGunDamage(val.damage, val.numberOfProjectiles, component) * 55f * (val.bulletDamageMultiplier * component.bulletDamageMultiplier);
				TryAdd(list, "DMG", before2, after2, "f0");
				TryAdd(list, "Knockback", val.knockback, ApplyKnockback(val.knockback, val.numberOfProjectiles, component), "f2");
				TryAdd(list, "Damage Grow", val.damageAfterDistanceMultiplier, val.damageAfterDistanceMultiplier * component.damageAfterDistanceMultiplier, "f2");
				TryAdd(list, "Bullet Slow", val.slow, val.slow + component.slow, "f2");
				TryAdd(list, "Attack SPD", val.attackSpeed * val.attackSpeedMultiplier, val.attackSpeed * component.attackSpeed * val.attackSpeedMultiplier, "f2", "s");
				TryAdd(list, "Bullet SPD", val.projectileSpeed, val.projectileSpeed * component.projectileSpeed, "f2");
				TryAdd(list, "Projectile SPD", val.projectielSimulatonSpeed, val.projectielSimulatonSpeed * component.projectielSimulatonSpeed, "f2");
				TryAdd(list, "Bullet Gravity", val.gravity, val.gravity * component.gravity, "f2");
				TryAdd(list, "Bullets", val.numberOfProjectiles, val.numberOfProjectiles + component.numberOfProjectiles, "f0");
				TryAdd(list, "Bounces", val.reflects, val.reflects + component.reflects, "f0");
				TryAdd(list, "Bursts", val.bursts, val.bursts + component.bursts, "f0");
				if (component.destroyBulletAfter != 0f)
				{
					TryAdd(list, "Bullet Range", val.destroyBulletAfter, component.destroyBulletAfter, "f2");
				}
				else
				{
					TryAdd(list, "Bullet Range", val.destroyBulletAfter, val.destroyBulletAfter + component.destroyBulletAfter, "f2");
				}
			}
			if ((Object)(object)component != (Object)null && (Object)(object)val3 != (Object)null)
			{
				float before3 = (val3.reloadTime + val3.reloadTimeAdd) * val3.reloadTimeMultiplier;
				float after3 = (val3.reloadTime + val3.reloadTimeAdd + component.reloadTimeAdd) * (val3.reloadTimeMultiplier * component.reloadTime);
				TryAdd(list, "Reload Time", before3, after3, "f2", "s");
				TryAdd(list, "Ammo", val3.maxAmmo, Mathf.Clamp(val3.maxAmmo + component.ammo, 1, 90), "f0");
			}
			return list;
		}

		public static IReadOnlyList<StatDeltaLine> ComputeRemoval(Player player, CardInfo card)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)card == (Object)null)
			{
				return Array.Empty<StatDeltaLine>();
			}
			GameObject obj = (((Object)(object)card.sourceCard != (Object)null) ? ((Component)card.sourceCard).gameObject : ((Component)card).gameObject);
			Gun component = obj.GetComponent<Gun>();
			CharacterStatModifiers component2 = obj.GetComponent<CharacterStatModifiers>();
			Block componentInChildren = obj.GetComponentInChildren<Block>();
			if (!HasStatTemplate(component, component2, componentInChildren))
			{
				return Array.Empty<StatDeltaLine>();
			}
			Gun val = player.data?.weaponHandler?.gun;
			Block val2 = player.data?.block;
			CharacterData data = player.data;
			CharacterStatModifiers component3 = ((Component)player).GetComponent<CharacterStatModifiers>();
			GunAmmo val3 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInChildren<GunAmmo>() : null);
			List<StatDeltaLine> list = new List<StatDeltaLine>();
			if ((Object)(object)component2 != (Object)null && (Object)(object)data != (Object)null && (Object)(object)component3 != (Object)null)
			{
				TryAdd(list, "HP", data.maxHealth, SafeDivide(data.maxHealth, component2.health), "f0");
				TryAdd(list, "Lives", (float)component3.respawns + 1f, (float)(component3.respawns - component2.respawns) + 1f, "f0");
				TryAdd(list, "Move SPD", component3.movementSpeed, SafeDivide(component3.movementSpeed, component2.movementSpeed), "f2");
				TryAdd(list, "Jump Height", component3.jump, SafeDivide(component3.jump, component2.jump), "f2");
				TryAdd(list, "Player Size", component3.sizeMultiplier, SafeDivide(component3.sizeMultiplier, component2.sizeMultiplier), "f2");
				TryAdd(list, "Life Steal", component3.lifeSteal, component3.lifeSteal - component2.lifeSteal, "f2");
			}
			if ((Object)(object)componentInChildren != (Object)null && (Object)(object)val2 != (Object)null)
			{
				float num = val2.Cooldown();
				float num2 = SafeDivide(num, val2.cdMultiplier * componentInChildren.cdMultiplier);
				num2 = (num2 - val2.cdAdd - componentInChildren.cdAdd) / Mathf.Max(val2.cdMultiplier, 0.0001f);
				TryAdd(list, "Block CD", num, num2, "f2", "s");
				TryAdd(list, "Block Count", (float)val2.additionalBlocks + 1f, (float)(val2.additionalBlocks - componentInChildren.additionalBlocks) + 1f, "f0");
			}
			if ((Object)(object)component != (Object)null && (Object)(object)val != (Object)null)
			{
				float before = val.damage * 55f * val.bulletDamageMultiplier;
				float after = InverseApplyGunDamage(val.damage, val.numberOfProjectiles, component) * 55f * SafeDivide(val.bulletDamageMultiplier, component.bulletDamageMultiplier);
				TryAdd(list, "DMG", before, after, "f0");
				TryAdd(list, "Knockback", val.knockback, InverseApplyKnockback(val.knockback, val.numberOfProjectiles, component), "f2");
				TryAdd(list, "Damage Grow", val.damageAfterDistanceMultiplier, SafeDivide(val.damageAfterDistanceMultiplier, component.damageAfterDistanceMultiplier), "f2");
				TryAdd(list, "Bullet Slow", val.slow, val.slow - component.slow, "f2");
				TryAdd(list, "Attack SPD", val.attackSpeed * val.attackSpeedMultiplier, SafeDivide(val.attackSpeed, component.attackSpeed) * val.attackSpeedMultiplier, "f2", "s");
				TryAdd(list, "Bullet SPD", val.projectileSpeed, SafeDivide(val.projectileSpeed, component.projectileSpeed), "f2");
				TryAdd(list, "Projectile SPD", val.projectielSimulatonSpeed, SafeDivide(val.projectielSimulatonSpeed, component.projectielSimulatonSpeed), "f2");
				TryAdd(list, "Bullet Gravity", val.gravity, SafeDivide(val.gravity, component.gravity), "f2");
				TryAdd(list, "Bullets", val.numberOfProjectiles, val.numberOfProjectiles - component.numberOfProjectiles, "f0");
				TryAdd(list, "Bounces", val.reflects, val.reflects - component.reflects, "f0");
				TryAdd(list, "Bursts", val.bursts, val.bursts - component.bursts, "f0");
				if (component.destroyBulletAfter != 0f)
				{
					TryAdd(list, "Bullet Range", val.destroyBulletAfter, val.destroyBulletAfter - component.destroyBulletAfter, "f2");
				}
				else
				{
					TryAdd(list, "Bullet Range", val.destroyBulletAfter, val.destroyBulletAfter - component.destroyBulletAfter, "f2");
				}
			}
			if ((Object)(object)component != (Object)null && (Object)(object)val3 != (Object)null)
			{
				float before2 = (val3.reloadTime + val3.reloadTimeAdd) * val3.reloadTimeMultiplier;
				float after2 = (val3.reloadTime + val3.reloadTimeAdd - component.reloadTimeAdd) * SafeDivide(val3.reloadTimeMultiplier, component.reloadTime);
				TryAdd(list, "Reload Time", before2, after2, "f2", "s");
				TryAdd(list, "Ammo", val3.maxAmmo, Mathf.Clamp(val3.maxAmmo - component.ammo, 1, 90), "f0");
			}
			return list;
		}

		internal static bool HasStatTemplate(Gun cardGun, CharacterStatModifiers cardPlayer, Block cardBlock)
		{
			if ((Object)(object)cardGun != (Object)null && GunHasChanges(cardGun))
			{
				return true;
			}
			if ((Object)(object)cardPlayer != (Object)null && PlayerHasChanges(cardPlayer))
			{
				return true;
			}
			if ((Object)(object)cardBlock != (Object)null && BlockHasChanges(cardBlock))
			{
				return true;
			}
			return false;
		}

		private static bool GunHasChanges(Gun g)
		{
			if (Mathf.Approximately(g.damage, 1f) && Mathf.Approximately(g.bulletDamageMultiplier, 1f) && Mathf.Approximately(g.knockback, 1f) && Mathf.Approximately(g.attackSpeed, 1f) && Mathf.Approximately(g.projectileSpeed, 1f) && Mathf.Approximately(g.projectielSimulatonSpeed, 1f) && Mathf.Approximately(g.gravity, 1f) && Mathf.Approximately(g.damageAfterDistanceMultiplier, 1f) && Mathf.Approximately(g.reloadTime, 1f) && Mathf.Approximately(g.reloadTimeAdd, 0f) && g.ammo == 0 && g.numberOfProjectiles == 0 && g.reflects == 0 && g.bursts == 0 && g.slow == 0f)
			{
				return g.destroyBulletAfter != 0f;
			}
			return true;
		}

		private static bool PlayerHasChanges(CharacterStatModifiers s)
		{
			if (Mathf.Approximately(s.health, 1f) && Mathf.Approximately(s.movementSpeed, 1f) && Mathf.Approximately(s.jump, 1f) && Mathf.Approximately(s.sizeMultiplier, 1f) && s.respawns == 0)
			{
				return s.lifeSteal != 0f;
			}
			return true;
		}

		private static bool BlockHasChanges(Block b)
		{
			if (Mathf.Approximately(b.cdMultiplier, 1f) && b.cdAdd == 0f)
			{
				return b.additionalBlocks != 0;
			}
			return true;
		}

		private static float ProjectileBlendFactor(int cardProjectiles, int currentProjectiles)
		{
			if (cardProjectiles == 0 || currentProjectiles == 1)
			{
				return 1f;
			}
			return (float)cardProjectiles / (float)(cardProjectiles + currentProjectiles);
		}

		private static float ApplyGunDamage(float currentDamage, int currentProjectiles, Gun cardGun)
		{
			float num = ProjectileBlendFactor(cardGun.numberOfProjectiles, currentProjectiles);
			return Mathf.Max(currentDamage * (1f - num * (1f - cardGun.damage)), 0.25f);
		}

		private static float ApplyKnockback(float currentKnockback, int currentProjectiles, Gun cardGun)
		{
			float num = ProjectileBlendFactor(cardGun.numberOfProjectiles, currentProjectiles);
			return currentKnockback * (1f - num * (1f - cardGun.knockback));
		}

		private static float SafeDivide(float value, float divisor)
		{
			if (Mathf.Abs(divisor) < 0.0001f)
			{
				return value;
			}
			return value / divisor;
		}

		private static float InverseApplyGunDamage(float currentDamage, int currentProjectiles, Gun cardGun)
		{
			int currentProjectiles2 = Mathf.Max(1, currentProjectiles - cardGun.numberOfProjectiles);
			float num = ProjectileBlendFactor(cardGun.numberOfProjectiles, currentProjectiles2);
			float num2 = 1f - num * (1f - cardGun.damage);
			if (Mathf.Abs(num2) < 0.0001f)
			{
				return currentDamage;
			}
			return Mathf.Max(currentDamage / num2, 0.25f);
		}

		private static float InverseApplyKnockback(float currentKnockback, int currentProjectiles, Gun cardGun)
		{
			int currentProjectiles2 = Mathf.Max(1, currentProjectiles - cardGun.numberOfProjectiles);
			float num = ProjectileBlendFactor(cardGun.numberOfProjectiles, currentProjectiles2);
			float num2 = 1f - num * (1f - cardGun.knockback);
			if (Mathf.Abs(num2) < 0.0001f)
			{
				return currentKnockback;
			}
			return currentKnockback / num2;
		}

		private static void TryAdd(List<StatDeltaLine> lines, string label, float before, float after, string format, string suffix = "")
		{
			if (!(Mathf.Abs(before - after) < 0.0001f))
			{
				lines.Add(new StatDeltaLine(label, before.ToString(format) + suffix, after.ToString(format) + suffix));
			}
		}
	}
	internal static class StatTemplateDeltaRegistrar
	{
		internal static void Init()
		{
			CardManager.AddAllCardsCallback((Action<CardInfo[]>)RegisterAll);
			IOLog.Line("StatTemplateDeltaRegistrar — waiting for CardManager.FirstTimeStart.");
		}

		private static void RegisterAll(CardInfo[] cards)
		{
			IOLog.Section("StatTemplateDeltaRegistrar — RegisterAll");
			int num = 0;
			int num2 = 0;
			foreach (CardInfo val in cards)
			{
				if ((Object)(object)val == (Object)null || string.IsNullOrEmpty(val.cardName))
				{
					continue;
				}
				if (CardDeltaRegistry.IsRegistered(val.cardName))
				{
					num2++;
					continue;
				}
				GameObject obj = (((Object)(object)val.sourceCard != (Object)null) ? ((Component)val.sourceCard).gameObject : ((Component)val).gameObject);
				Gun component = obj.GetComponent<Gun>();
				CharacterStatModifiers component2 = obj.GetComponent<CharacterStatModifiers>();
				Block componentInChildren = obj.GetComponentInChildren<Block>();
				if (StatTemplateDeltaProvider.HasStatTemplate(component, component2, componentInChildren))
				{
					CardDeltaRegistry.Register(val.cardName, StatTemplateDeltaProvider.Compute);
					num++;
				}
			}
			IOLog.Line($"Registered {num} stat-template cards (skipped {num2} already registered).");
		}
	}
}
namespace InfoOverhaul.Compat
{
	internal static class MfmTier2Compat
	{
		internal static void Init()
		{
			CardManager.AddAllCardsCallback((Action<CardInfo[]>)delegate
			{
				RegisterEffectNotes();
			});
		}

		private static void RegisterEffectNotes()
		{
			IOLog.Section("MfmTier2Compat — RegisterEffectNotes");
			IOLog.Line("MfmTier2Compat ready (no notes registered yet — add per card as validated).");
		}
	}
}

Keybound.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Keybound.Cards;
using Keybound.Compat;
using Keybound.Core;
using Keybound.Effects;
using Keybound.UI;
using Microsoft.CodeAnalysis;
using TMPro;
using UnboundLib.Cards;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: AssemblyCompany("Keybound")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+146ac727a7fc6b83f382d57f53cce40478349c58")]
[assembly: AssemblyProduct("Keybound Mod for ROUNDS")]
[assembly: AssemblyTitle("Keybound")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 Keybound
{
	internal static class KLog
	{
		private static ManualLogSource Logger => Plugin.Logger;

		internal static void Section(string title)
		{
			ManualLogSource logger = Logger;
			if (logger != null)
			{
				logger.LogInfo((object)"=====================");
			}
			ManualLogSource logger2 = Logger;
			if (logger2 != null)
			{
				logger2.LogInfo((object)("[Keybound] " + title));
			}
			ManualLogSource logger3 = Logger;
			if (logger3 != null)
			{
				logger3.LogInfo((object)"=====================");
			}
		}

		internal static void Line(string message)
		{
			ManualLogSource logger = Logger;
			if (logger != null)
			{
				logger.LogInfo((object)("[Keybound] " + message));
			}
		}

		internal static void Warn(string message)
		{
			ManualLogSource logger = Logger;
			if (logger != null)
			{
				logger.LogWarning((object)("[Keybound] " + message));
			}
		}

		internal static void Error(string message)
		{
			ManualLogSource logger = Logger;
			if (logger != null)
			{
				logger.LogError((object)("[Keybound] " + message));
			}
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("Keybound", "Keybound Mod for ROUNDS", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		internal static string PluginDirectory { get; private set; }

		private void Awake()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0072: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? "";
			KLog.Section("Plugin Awake");
			KLog.Line("PluginDirectory = " + PluginDirectory);
			new Harmony("Keybound").PatchAll();
			((Component)this).gameObject.AddComponent<EffectStackManager>();
			GameObject val = new GameObject("KB_UIRoot");
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<KeybindModalUI>();
			val.AddComponent<EffectStackOverlay>();
			KLog.Line("Plugin Keybound loaded.");
		}

		private void Start()
		{
			KeyboundCardRegistrar.RegisterAll();
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Keybound";

		public const string PLUGIN_NAME = "Keybound Mod for ROUNDS";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace Keybound.UI
{
	public class EffectStackOverlay : MonoBehaviour
	{
		private sealed class PlayerEffectRow
		{
			internal GameObject Root;

			private RectTransform _slotRow;

			private readonly List<EffectSlotView> _slots = new List<EffectSlotView>();

			private Action<KeyboundBinding, Vector3> _onHover;

			private Action _onHoverExit;

			internal static PlayerEffectRow Create(Transform parent, int playerID, Action<KeyboundBinding, Vector3> onHover, Action onHoverExit)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Expected O, but got Unknown
				GameObject val = new GameObject($"EffectRow_P{playerID}");
				val.transform.SetParent(parent, false);
				val.AddComponent<RectTransform>();
				LayoutElement obj = val.AddComponent<LayoutElement>();
				obj.preferredHeight = 35f;
				obj.minHeight = 35f;
				HorizontalLayoutGroup obj2 = val.AddComponent<HorizontalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f;
				((LayoutGroup)obj2).childAlignment = (TextAnchor)5;
				((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = false;
				((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = false;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
				return new PlayerEffectRow
				{
					Root = val,
					_slotRow = val.GetComponent<RectTransform>(),
					_onHover = onHover,
					_onHoverExit = onHoverExit
				};
			}

			internal void Refresh(IReadOnlyList<KeyboundBinding> bindings)
			{
				Root.SetActive(true);
				EnsureSlotCount(bindings.Count);
				for (int i = 0; i < bindings.Count; i++)
				{
					_slots[i].Bind(bindings[i]);
				}
				for (int j = bindings.Count; j < _slots.Count; j++)
				{
					_slots[j].Root.SetActive(false);
				}
			}

			private void EnsureSlotCount(int count)
			{
				while (_slots.Count < count)
				{
					EffectSlotView item = EffectSlotView.Create((Transform)(object)_slotRow, _onHover, _onHoverExit);
					_slots.Add(item);
				}
			}
		}

		private sealed class EffectSlotView : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
		{
			internal GameObject Root;

			private Image _bg;

			private TextMeshProUGUI _label;

			private static readonly Color CooldownRed = new Color(0.55f, 0.12f, 0.12f, 0.95f);

			private static readonly Color ReadyGreen = new Color(0.12f, 0.55f, 0.18f, 0.95f);

			private static readonly Color BorderRed = new Color(0.95f, 0.2f, 0.2f, 1f);

			private static readonly Color BorderGreen = new Color(0.2f, 1f, 0.2f, 1f);

			private KeyboundBinding _binding;

			private Action<KeyboundBinding, Vector3> _onHover;

			private Action _onHoverExit;

			internal static EffectSlotView Create(Transform parent, Action<KeyboundBinding, Vector3> onHover, Action onHoverExit)
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Expected O, but got Unknown
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = new GameObject("EffectSlot");
				val.transform.SetParent(parent, false);
				val.AddComponent<RectTransform>().sizeDelta = new Vector2(35f, 35f);
				LayoutElement obj = val.AddComponent<LayoutElement>();
				obj.preferredWidth = 35f;
				obj.preferredHeight = 35f;
				EffectSlotView effectSlotView = val.AddComponent<EffectSlotView>();
				effectSlotView._onHover = onHover;
				effectSlotView._onHoverExit = onHoverExit;
				effectSlotView.Root = val;
				effectSlotView.Build();
				return effectSlotView;
			}

			private void Build()
			{
				//IL_0017: 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_0046: Unknown result type (might be due to invalid IL or missing references)
				_bg = ((Component)this).gameObject.AddComponent<Image>();
				((Graphic)_bg).color = CooldownRed;
				Outline obj = ((Component)_bg).gameObject.AddComponent<Outline>();
				((Shadow)obj).effectColor = BorderRed;
				((Shadow)obj).effectDistance = new Vector2(3f, -3f);
				_label = UIHelper.CreateText(((Component)this).transform, "Abbr", "—", 12, (TextAlignmentOptions)514);
			}

			internal void Bind(KeyboundBinding binding)
			{
				_binding = binding;
				((TMP_Text)_label).text = Abbreviate(binding.CardName);
				RefreshVisual();
			}

			private void Update()
			{
				if (_binding != null)
				{
					RefreshVisual();
				}
			}

			private void RefreshVisual()
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: 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_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				float num = 1f - _binding.CooldownFill();
				((Graphic)_bg).color = Color.Lerp(CooldownRed, ReadyGreen, num);
				Outline obj = ((Component)_bg).GetComponent<Outline>() ?? ((Component)_bg).gameObject.AddComponent<Outline>();
				((Shadow)obj).effectColor = (_binding.IsReady() ? BorderGreen : BorderRed);
				((Shadow)obj).effectDistance = new Vector2(3f, -3f);
			}

			public void OnPointerEnter(PointerEventData _)
			{
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				if (_binding != null)
				{
					_onHover?.Invoke(_binding, ((Component)this).transform.position);
				}
			}

			public void OnPointerExit(PointerEventData _)
			{
				_onHoverExit?.Invoke();
			}

			private static string Abbreviate(string name)
			{
				if (string.IsNullOrEmpty(name))
				{
					return "?";
				}
				if (name.Length == 1)
				{
					return name.ToUpper();
				}
				return char.ToUpper(name[0]) + name.Substring(1, 1).ToLower();
			}
		}

		public static EffectStackOverlay instance;

		private const float RowHeight = 35f;

		private const float RowSpacing = 4f;

		private const float SlotSize = 35f;

		private Canvas _canvas;

		private RectTransform _container;

		private readonly Dictionary<int, PlayerEffectRow> _playerRows = new Dictionary<int, PlayerEffectRow>();

		private GameObject _hoverCard;

		private void Awake()
		{
			instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			BuildUI();
			((Component)_canvas).gameObject.SetActive(false);
		}

		private void BuildUI()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			_canvas = UIHelper.CreateFullscreenCanvas("KB_EffectStack", 45);
			_container = UIHelper.CreatePanel(((Component)_canvas).transform, "EffectContainer", new Vector2(0.55f, 0.02f), new Vector2(0.98f, 0.3f));
			VerticalLayoutGroup obj = ((Component)_container).gameObject.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)obj).childAlignment = (TextAnchor)8;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)obj).spacing = 4f;
			((LayoutGroup)obj).padding = new RectOffset(0, 4, 4, 0);
		}

		public void RefreshAll()
		{
			if ((Object)(object)EffectStackManager.instance == (Object)null)
			{
				HideAll();
				return;
			}
			bool flag = false;
			HashSet<int> hashSet = new HashSet<int>();
			foreach (KeyValuePair<int, IReadOnlyList<KeyboundBinding>> allBinding in EffectStackManager.instance.GetAllBindings())
			{
				hashSet.Add(allBinding.Key);
				GetOrCreateRow(allBinding.Key).Refresh(allBinding.Value);
				flag = true;
			}
			foreach (KeyValuePair<int, PlayerEffectRow> playerRow in _playerRows)
			{
				if (!hashSet.Contains(playerRow.Key))
				{
					playerRow.Value.Root.SetActive(false);
				}
			}
			if (!flag)
			{
				HideAll();
			}
			else
			{
				((Component)_canvas).gameObject.SetActive(true);
			}
		}

		public void Refresh(int playerID)
		{
			RefreshAll();
		}

		public void HideAll()
		{
			ClearHover();
			foreach (PlayerEffectRow value in _playerRows.Values)
			{
				value.Root.SetActive(false);
			}
			if ((Object)(object)_canvas != (Object)null)
			{
				((Component)_canvas).gameObject.SetActive(false);
			}
		}

		private void Update()
		{
			if (!((Object)(object)_canvas == (Object)null) && ((Component)_canvas).gameObject.activeSelf && !IsGameActive())
			{
				HideAll();
			}
		}

		private PlayerEffectRow GetOrCreateRow(int playerID)
		{
			if (_playerRows.TryGetValue(playerID, out var value))
			{
				return value;
			}
			value = PlayerEffectRow.Create((Transform)(object)_container, playerID, OnSlotHover, OnSlotHoverExit);
			_playerRows[playerID] = value;
			return value;
		}

		private void OnSlotHover(KeyboundBinding binding, Vector3 worldPos)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			ClearHover();
			if ((Object)(object)CardChoice.instance == (Object)null)
			{
				return;
			}
			CardInfo val = binding.Card ?? FindCardTemplate(binding.CardName);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			_hoverCard = CardChoice.instance.AddCardVisual(val, worldPos);
			if (!((Object)(object)_hoverCard == (Object)null))
			{
				Collider2D[] componentsInChildren = ((Component)_hoverCard.transform.root).GetComponentsInChildren<Collider2D>();
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Behaviour)componentsInChildren[i]).enabled = false;
				}
				Canvas componentInChildren = _hoverCard.GetComponentInChildren<Canvas>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.sortingLayerName = "MostFront";
				}
				RectTransform component = ((Component)UIHelper.CreateText(_hoverCard.transform, "KeyLabel", "Bound to " + KeybindModalUI.FormatKey(binding.Key), 18, (TextAlignmentOptions)1026, (Color?)new Color(0.75f, 0.9f, 1f))).GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0f, 0f);
				component.anchorMax = new Vector2(1f, 0.18f);
				Vector2 offsetMin = (component.offsetMax = Vector2.zero);
				component.offsetMin = offsetMin;
			}
		}

		private void OnSlotHoverExit()
		{
			ClearHover();
		}

		private void ClearHover()
		{
			if ((Object)(object)_hoverCard != (Object)null)
			{
				Object.Destroy((Object)(object)_hoverCard);
				_hoverCard = null;
			}
		}

		private static CardInfo FindCardTemplate(string cardName)
		{
			if (CardChoice.instance?.cards == null)
			{
				return null;
			}
			CardInfo[] cards = CardChoice.instance.cards;
			foreach (CardInfo val in cards)
			{
				if ((Object)(object)val != (Object)null && val.cardName == cardName)
				{
					return val;
				}
			}
			return null;
		}

		private static bool IsGameActive()
		{
			if ((Object)(object)GameManager.instance == (Object)null)
			{
				return false;
			}
			if (!GameManager.instance.isPlaying)
			{
				return false;
			}
			if (PlayerManager.instance?.players == null || PlayerManager.instance.players.Count == 0)
			{
				return false;
			}
			return true;
		}
	}
	public class KeybindModalUI : MonoBehaviour
	{
		public static KeybindModalUI instance;

		private const int KeyA = 97;

		private const int KeyZ = 122;

		private const int KeyAlpha0 = 48;

		private const int KeyAlpha9 = 57;

		private Canvas _canvas;

		private TextMeshProUGUI _messageText;

		private Button _bindButton;

		private Image _bindImage;

		private TextMeshProUGUI _bindLabel;

		private Action<int> _onConfirm;

		private Action _onCancel;

		private int _pickerID;

		private CardInfo _card;

		private int? _pendingKey;

		private static readonly Color PanelBg = new Color(0.04f, 0.06f, 0.12f, 1f);

		private static readonly Color CancelBg = new Color(0.4f, 0.1f, 0.1f, 0.95f);

		private static readonly Color BindReadyBg = new Color(0.1f, 0.45f, 0.12f, 0.95f);

		private static readonly Color BindGrayBg = new Color(0.18f, 0.18f, 0.18f, 0.55f);

		private void Awake()
		{
			instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			BuildUI();
			((Component)_canvas).gameObject.SetActive(false);
		}

		private void BuildUI()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Expected O, but got Unknown
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Expected O, but got Unknown
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Expected O, but got Unknown
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Expected O, but got Unknown
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			_canvas = UIHelper.CreateFullscreenCanvas("KB_KeybindModal", 190);
			UIHelper.CreatePanel(((Component)_canvas).transform, "Dim", Vector2.zero, Vector2.one, (Color?)new Color(0f, 0f, 0f, 0.55f));
			RectTransform val = UIHelper.CreatePanel(((Component)_canvas).transform, "Panel", new Vector2(0.25f, 0.35f), new Vector2(0.75f, 0.65f), PanelBg);
			UIHelper.CreateText((Transform)(object)val, "Title", "Bind Key", 28, (TextAlignmentOptions)258, (Color?)new Color(0.9f, 0.93f, 1f));
			_messageText = UIHelper.CreateText((Transform)(object)val, "Message", "Press a key to bind this effect.", 22, (TextAlignmentOptions)4098, (Color?)new Color(0.88f, 0.92f, 1f));
			RectTransform component = ((Component)_messageText).GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.05f, 0.35f);
			component.anchorMax = new Vector2(0.95f, 0.75f);
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			((UnityEvent)UIHelper.CreateButton((Transform)(object)val, "CancelBtn", "[Cancel]", new Vector2(0.08f, 0.1f), new Vector2(0.42f, 0.28f), 20, CancelBg).onClick).AddListener(new UnityAction(OnCancelClicked));
			GameObject val2 = new GameObject("BindBtn");
			val2.transform.SetParent((Transform)(object)val, false);
			RectTransform obj = val2.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0.58f, 0.1f);
			obj.anchorMax = new Vector2(0.92f, 0.28f);
			offsetMin = (obj.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			_bindImage = val2.AddComponent<Image>();
			((Graphic)_bindImage).color = BindGrayBg;
			_bindButton = val2.AddComponent<Button>();
			((Selectable)_bindButton).targetGraphic = (Graphic)(object)_bindImage;
			((Selectable)_bindButton).interactable = false;
			((UnityEvent)_bindButton.onClick).AddListener(new UnityAction(OnBindClicked));
			GameObject val3 = new GameObject("Label");
			val3.transform.SetParent(val2.transform, false);
			RectTransform obj2 = val3.AddComponent<RectTransform>();
			obj2.anchorMin = Vector2.zero;
			obj2.anchorMax = Vector2.one;
			offsetMin = (obj2.offsetMax = Vector2.zero);
			obj2.offsetMin = offsetMin;
			_bindLabel = val3.AddComponent<TextMeshProUGUI>();
			((TMP_Text)_bindLabel).text = "[Bind Key]";
			((TMP_Text)_bindLabel).fontSize = 20f;
			((TMP_Text)_bindLabel).alignment = (TextAlignmentOptions)514;
			((Graphic)_bindLabel).color = new Color(0.45f, 0.45f, 0.45f);
		}

		public void Show(int pickerID, CardInfo card, Action<int> onConfirm, Action onCancel)
		{
			_pickerID = pickerID;
			_card = card;
			_onConfirm = onConfirm;
			_onCancel = onCancel;
			_pendingKey = null;
			((TMP_Text)_messageText).text = "Press a key to bind <b>" + card.cardName + "</b>.";
			RefreshBindButton();
			((Component)_canvas).gameObject.SetActive(true);
			KLog.Line($"Keybind modal shown for '{card.cardName}' (picker={pickerID}).");
		}

		public void Hide()
		{
			((Component)_canvas).gameObject.SetActive(false);
			_onConfirm = null;
			_onCancel = null;
			_card = null;
			_pendingKey = null;
		}

		private void Update()
		{
			if (!((Component)_canvas).gameObject.activeSelf || (Object)(object)_card == (Object)null)
			{
				return;
			}
			if (InputCompat.GetKeyDown(27))
			{
				OnCancelClicked();
				return;
			}
			int[] bindableKeys = GetBindableKeys();
			foreach (int num in bindableKeys)
			{
				if (InputCompat.GetKeyDown(num))
				{
					EffectStackManager effectStackManager = EffectStackManager.instance;
					if (effectStackManager != null && effectStackManager.IsKeyTaken(_pickerID, num))
					{
						((TMP_Text)_messageText).text = "<color=#ff8888>" + FormatKey(num) + " is already bound.</color>";
						_pendingKey = null;
						RefreshBindButton();
						break;
					}
					_pendingKey = num;
					((TMP_Text)_messageText).text = "Bind <b>" + _card.cardName + "</b> to <b>" + FormatKey(num) + "</b>?";
					RefreshBindButton();
					break;
				}
			}
		}

		private void RefreshBindButton()
		{
			//IL_0028: 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_0051: 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)
			bool hasValue = _pendingKey.HasValue;
			((Selectable)_bindButton).interactable = hasValue;
			((Graphic)_bindImage).color = (hasValue ? BindReadyBg : BindGrayBg);
			((Graphic)_bindLabel).color = (Color)(hasValue ? Color.white : new Color(0.45f, 0.45f, 0.45f));
		}

		private void OnBindClicked()
		{
			if (_pendingKey.HasValue)
			{
				int value = _pendingKey.Value;
				Action<int> onConfirm = _onConfirm;
				Hide();
				onConfirm?.Invoke(value);
			}
		}

		private void OnCancelClicked()
		{
			Action onCancel = _onCancel;
			Hide();
			onCancel?.Invoke();
		}

		private static int[] GetBindableKeys()
		{
			int[] array = new int[36];
			int num = 0;
			for (int i = 97; i <= 122; i++)
			{
				array[num++] = i;
			}
			for (int j = 48; j <= 57; j++)
			{
				array[num++] = j;
			}
			return array;
		}

		internal static string FormatKey(int key)
		{
			if (key >= 48 && key <= 57)
			{
				return (key - 48).ToString();
			}
			if (key >= 97 && key <= 122)
			{
				return ((char)key).ToString().ToUpper();
			}
			return key.ToString();
		}
	}
	internal static class UIHelper
	{
		public static Canvas CreateFullscreenCanvas(string name, int sortOrder = 100)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_000c: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			Object.DontDestroyOnLoad((Object)val);
			Canvas val2 = val.AddComponent<Canvas>();
			val2.renderMode = (RenderMode)0;
			val2.sortingOrder = sortOrder;
			CanvasScaler obj = val.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)1;
			obj.referenceResolution = new Vector2(1920f, 1080f);
			val.AddComponent<GraphicRaycaster>();
			return val2;
		}

		public static RectTransform CreatePanel(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Color? bg = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0030: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = anchorMin;
			obj.anchorMax = anchorMax;
			Vector2 offsetMin = (obj.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			if (bg.HasValue)
			{
				((Graphic)val.AddComponent<Image>()).color = bg.Value;
			}
			return obj;
		}

		public static TextMeshProUGUI CreateText(Transform parent, string name, string text, int fontSize = 24, TextAlignmentOptions alignment = 514, Color? color = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			Vector2 offsetMin = (obj.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			TextMeshProUGUI obj2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj2).text = text;
			((TMP_Text)obj2).fontSize = fontSize;
			((TMP_Text)obj2).alignment = alignment;
			((Graphic)obj2).color = (Color)(((??)color) ?? Color.white);
			return obj2;
		}

		public static Button CreateButton(Transform parent, string name, string label, Vector2 anchorMin, Vector2 anchorMax, int fontSize = 20, Color? bgColor = null, Color? textColor = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0030: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = anchorMin;
			obj.anchorMax = anchorMax;
			Vector2 offsetMin = (obj.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = (Color)(((??)bgColor) ?? new Color(0.2f, 0.2f, 0.2f, 0.9f));
			Button obj2 = val.AddComponent<Button>();
			((Selectable)obj2).targetGraphic = (Graphic)(object)val2;
			ColorBlock colors = default(ColorBlock);
			((ColorBlock)(ref colors)).normalColor = Color.white;
			((ColorBlock)(ref colors)).highlightedColor = new Color(1.15f, 1.15f, 1.15f);
			((ColorBlock)(ref colors)).pressedColor = new Color(0.8f, 0.8f, 0.8f);
			((ColorBlock)(ref colors)).disabledColor = Color.white;
			((ColorBlock)(ref colors)).colorMultiplier = 1f;
			((ColorBlock)(ref colors)).fadeDuration = 0.1f;
			((Selectable)obj2).colors = colors;
			GameObject val3 = new GameObject("Label");
			val3.transform.SetParent(val.transform, false);
			RectTransform obj3 = val3.AddComponent<RectTransform>();
			obj3.anchorMin = Vector2.zero;
			obj3.anchorMax = Vector2.one;
			offsetMin = (obj3.offsetMax = Vector2.zero);
			obj3.offsetMin = offsetMin;
			TextMeshProUGUI obj4 = val3.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj4).text = label;
			((TMP_Text)obj4).fontSize = fontSize;
			((TMP_Text)obj4).alignment = (TextAlignmentOptions)514;
			((Graphic)obj4).color = (Color)(((??)textColor) ?? Color.white);
			return obj2;
		}
	}
}
namespace Keybound.Patches
{
	[HarmonyPatch]
	internal static class DeckPickCompatPatch
	{
		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("DeckBuilder.GameIntegration.DeckPickPatch");
			if (!(type == null))
			{
				return AccessTools.Method(type, "ApplyStats_Postfix", (Type[])null, (Type[])null);
			}
			return null;
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool SuppressDeckConsume(ApplyCardStats __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			CardInfo componentInParent = ((Component)__instance).GetComponentInParent<CardInfo>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return true;
			}
			if (!KeyboundCardRegistry.IsKeybound(componentInParent.cardName))
			{
				return true;
			}
			KLog.Line("Suppressed DeckPickPatch consume for keybound card '" + componentInParent.cardName + "'.");
			return false;
		}
	}
	[HarmonyPatch]
	internal static class KeyboundPickPatches
	{
		internal static bool IsBindFlowActive;

		private static int _pickerID = -1;

		private static CardInfo _pendingCard;

		[HarmonyPatch(typeof(ApplyCardStats), "ApplyStats")]
		[HarmonyPrefix]
		private static bool ApplyStats_Prefix(ApplyCardStats __instance)
		{
			if ((Object)(object)CardChoice.instance == (Object)null || !CardChoice.instance.IsPicking)
			{
				return true;
			}
			CardInfo componentInParent = ((Component)__instance).GetComponentInParent<CardInfo>();
			if ((Object)(object)componentInParent == (Object)null || !KeyboundCardRegistry.IsKeybound(componentInParent.cardName))
			{
				return true;
			}
			int pickrID = CardChoice.instance.pickrID;
			if (!IsLocalPicker(pickrID))
			{
				return true;
			}
			KLog.Section("Keybind flow started — '" + componentInParent.cardName + "'");
			StartBindFlow(pickrID, componentInParent);
			return false;
		}

		[HarmonyPatch(typeof(CardChoice), "RPCA_DoEndPick")]
		[HarmonyPrefix]
		private static bool RPCA_DoEndPick_Prefix()
		{
			if (!IsBindFlowActive)
			{
				return true;
			}
			KLog.Line("RPCA_DoEndPick suppressed (keybind modal open).");
			return false;
		}

		[HarmonyPatch(typeof(CardBarHandler), "AddCard")]
		[HarmonyPrefix]
		private static bool CardBarHandler_AddCard_Prefix(CardInfo card)
		{
			if ((Object)(object)card == (Object)null)
			{
				return true;
			}
			if (!KeyboundCardRegistry.IsKeybound(card.cardName))
			{
				return true;
			}
			KLog.Line("Blocked card-bar add for keybound card '" + card.cardName + "'.");
			return false;
		}

		private static void StartBindFlow(int pickerID, CardInfo card)
		{
			_pickerID = pickerID;
			_pendingCard = card;
			IsBindFlowActive = true;
			KeybindModalUI.instance?.Show(pickerID, card, OnConfirm, OnCancel);
		}

		private static void OnConfirm(int key)
		{
			KLog.Section($"Keybind confirmed — {_pendingCard?.cardName} -> {key}");
			IsBindFlowActive = false;
			if ((Object)(object)_pendingCard != (Object)null)
			{
				EffectStackManager.instance?.AddBinding(_pickerID, _pendingCard, key);
				DeckBuilderBridge.ConsumeCard(_pickerID, _pendingCard);
			}
			PickPhaseHelper.EndPickPhase();
			_pendingCard = null;
		}

		private static void OnCancel()
		{
			KLog.Section("Keybind cancelled");
			IsBindFlowActive = false;
			PickPhaseHelper.RestorePickState(_pickerID, _pendingCard);
			_pendingCard = null;
		}

		private static bool IsLocalPicker(int pickerID)
		{
			Player val = PlayerManager.instance?.players?.Find((Player p) => p.playerID == pickerID);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			object obj = AccessTools.Field(typeof(CharacterData), "view")?.GetValue(val.data);
			if (obj == null)
			{
				return true;
			}
			PropertyInfo propertyInfo = AccessTools.Property(obj.GetType(), "IsMine");
			if (propertyInfo == null)
			{
				return true;
			}
			return (bool)propertyInfo.GetValue(obj, null);
		}
	}
}
namespace Keybound.Effects
{
	internal static class TeleportEffect
	{
		internal const string CardName = "Teleport";

		internal const float InitialDelay = 10f;

		internal const float Cooldown = 15f;

		internal static readonly KeyboundEffectDef Def = new KeyboundEffectDef
		{
			CardName = "Teleport",
			InitialDelay = 10f,
			Cooldown = 15f,
			Activate = TryTeleport
		};

		private static bool TryTeleport(Player player)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player?.data == (Object)null || (Object)(object)MainCam.instance?.cam == (Object)null)
			{
				return false;
			}
			Vector3 val = MainCam.instance.cam.ScreenToWorldPoint(InputCompat.MousePosition);
			val.z = 0f;
			PlayerCollision componentInParent = ((Component)player).GetComponentInParent<PlayerCollision>();
			if (componentInParent != null)
			{
				componentInParent.IgnoreWallForFrames(2);
			}
			((Component)player).transform.position = val;
			if ((Object)(object)player.data.playerVel != (Object)null)
			{
				Traverse.Create((object)player.data.playerVel).Field("velocity").SetValue((object)Vector2.zero);
			}
			player.data.sinceGrounded = 0f;
			KLog.Line($"Teleport activated for player {player.playerID} -> ({val.x:F1}, {val.y:F1}).");
			return true;
		}
	}
}
namespace Keybound.Core
{
	public class EffectStackManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <GetAllBindings>d__4 : IEnumerable<KeyValuePair<int, IReadOnlyList<KeyboundBinding>>>, IEnumerable, IEnumerator<KeyValuePair<int, IReadOnlyList<KeyboundBinding>>>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private KeyValuePair<int, IReadOnlyList<KeyboundBinding>> <>2__current;

			private int <>l__initialThreadId;

			public EffectStackManager <>4__this;

			private Dictionary<int, List<KeyboundBinding>>.Enumerator <>7__wrap1;

			KeyValuePair<int, IReadOnlyList<KeyboundBinding>> IEnumerator<KeyValuePair<int, IReadOnlyList<KeyboundBinding>>>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

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

			[DebuggerHidden]
			public <GetAllBindings>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = default(Dictionary<int, List<KeyboundBinding>>.Enumerator);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					int num = <>1__state;
					EffectStackManager effectStackManager = <>4__this;
					switch (num)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>7__wrap1 = effectStackManager._bindings.GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					}
					while (<>7__wrap1.MoveNext())
					{
						KeyValuePair<int, List<KeyboundBinding>> current = <>7__wrap1.Current;
						if (current.Value != null && current.Value.Count > 0)
						{
							<>2__current = new KeyValuePair<int, IReadOnlyList<KeyboundBinding>>(current.Key, current.Value);
							<>1__state = 1;
							return true;
						}
					}
					<>m__Finally1();
					<>7__wrap1 = default(Dictionary<int, List<KeyboundBinding>>.Enumerator);
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

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

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap1).Dispose();
			}

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

			[DebuggerHidden]
			IEnumerator<KeyValuePair<int, IReadOnlyList<KeyboundBinding>>> IEnumerable<KeyValuePair<int, IReadOnlyList<KeyboundBinding>>>.GetEnumerator()
			{
				<GetAllBindings>d__4 result;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					result = this;
				}
				else
				{
					result = new <GetAllBindings>d__4(0)
					{
						<>4__this = <>4__this
					};
				}
				return result;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<KeyValuePair<int, IReadOnlyList<KeyboundBinding>>>)this).GetEnumerator();
			}
		}

		public static EffectStackManager instance;

		private readonly Dictionary<int, List<KeyboundBinding>> _bindings = new Dictionary<int, List<KeyboundBinding>>();

		private bool _wasGameActive;

		private void Awake()
		{
			instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}

		internal IReadOnlyList<KeyboundBinding> GetBindings(int playerID)
		{
			if (!_bindings.TryGetValue(playerID, out var value))
			{
				return Array.Empty<KeyboundBinding>();
			}
			return value;
		}

		[IteratorStateMachine(typeof(<GetAllBindings>d__4))]
		internal IEnumerable<KeyValuePair<int, IReadOnlyList<KeyboundBinding>>> GetAllBindings()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetAllBindings>d__4(-2)
			{
				<>4__this = this
			};
		}

		internal bool IsKeyTaken(int playerID, int key)
		{
			return GetBindings(playerID).Any((KeyboundBinding b) => b.Key == key);
		}

		internal void AddBinding(int playerID, CardInfo card, int key)
		{
			if ((Object)(object)card == (Object)null || !KeyboundCardRegistry.TryGet(card.cardName, out var def))
			{
				KLog.Warn("AddBinding failed — '" + (card?.cardName ?? "null") + "' is not keybound.");
				return;
			}
			if (!_bindings.TryGetValue(playerID, out var value))
			{
				value = new List<KeyboundBinding>();
				_bindings[playerID] = value;
			}
			KeyboundBinding keyboundBinding = new KeyboundBinding
			{
				PlayerID = playerID,
				CardName = card.cardName,
				Card = card,
				Key = key,
				Def = def
			};
			keyboundBinding.ArmInitialDelay();
			value.Add(keyboundBinding);
			KLog.Line($"Bound '{card.cardName}' to {key} for player {playerID}.");
			EffectStackOverlay.instance?.RefreshAll();
		}

		internal void ClearAll()
		{
			_bindings.Clear();
			EffectStackOverlay.instance?.HideAll();
		}

		private void Update()
		{
			bool flag = IsGameActive();
			if (_wasGameActive && !flag)
			{
				ClearAll();
			}
			_wasGameActive = flag;
			if (!flag)
			{
				return;
			}
			Player localHumanPlayer = GetLocalHumanPlayer();
			if ((Object)(object)localHumanPlayer == (Object)null)
			{
				return;
			}
			foreach (KeyboundBinding binding in GetBindings(localHumanPlayer.playerID))
			{
				if (binding.IsReady() && InputCompat.GetKeyDown(binding.Key) && binding.Def.Activate(localHumanPlayer))
				{
					binding.ArmCooldown();
				}
			}
			EffectStackOverlay.instance?.RefreshAll();
		}

		private static bool IsGameActive()
		{
			if ((Object)(object)GameManager.instance == (Object)null)
			{
				return false;
			}
			if (!GameManager.instance.isPlaying)
			{
				return false;
			}
			if (PlayerManager.instance?.players == null || PlayerManager.instance.players.Count == 0)
			{
				return false;
			}
			return true;
		}

		internal static Player GetLocalHumanPlayer()
		{
			if ((Object)(object)PlayerManager.instance == (Object)null)
			{
				return null;
			}
			foreach (Player player in PlayerManager.instance.players)
			{
				if ((Object)(object)player == (Object)null)
				{
					continue;
				}
				PlayerAPI component = ((Component)player).GetComponent<PlayerAPI>();
				if (component == null || !((Behaviour)component).enabled)
				{
					object obj = AccessTools.Field(typeof(CharacterData), "view")?.GetValue(player.data);
					if (obj == null)
					{
						return player;
					}
					PropertyInfo propertyInfo = AccessTools.Property(obj.GetType(), "IsMine");
					if (propertyInfo == null)
					{
						return player;
					}
					if ((bool)propertyInfo.GetValue(obj, null))
					{
						return player;
					}
				}
			}
			return null;
		}
	}
	internal static class InputCompat
	{
		internal const int KeyEscape = 27;

		private static Type _keyCodeType;

		private static MethodInfo _getKeyDown;

		private static PropertyInfo _mousePosition;

		private static bool _resolved;

		private static bool _available;

		internal static Vector3 MousePosition
		{
			get
			{
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_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)
				Resolve();
				if (!_available)
				{
					return Vector3.zero;
				}
				try
				{
					return (Vector3)_mousePosition.GetValue(null, null);
				}
				catch (Exception ex)
				{
					KLog.Warn("InputCompat.MousePosition failed: " + ex.Message);
					return Vector3.zero;
				}
			}
		}

		internal static bool GetKeyDown(int keyCode)
		{
			Resolve();
			if (!_available)
			{
				return false;
			}
			try
			{
				object obj = Enum.ToObject(_keyCodeType, keyCode);
				return (bool)_getKeyDown.Invoke(null, new object[1] { obj });
			}
			catch (Exception ex)
			{
				KLog.Warn("InputCompat.GetKeyDown failed: " + ex.Message);
				return false;
			}
		}

		private static void Resolve()
		{
			if (_resolved)
			{
				return;
			}
			_resolved = true;
			try
			{
				_keyCodeType = Type.GetType("UnityEngine.KeyCode, UnityEngine.CoreModule") ?? Type.GetType("UnityEngine.KeyCode, UnityEngine");
				Type type = Type.GetType("UnityEngine.Input, UnityEngine.CoreModule") ?? Type.GetType("UnityEngine.Input, UnityEngine");
				if (_keyCodeType == null || type == null)
				{
					KLog.Warn("InputCompat: UnityEngine.Input/KeyCode not found in CoreModule.");
					return;
				}
				_getKeyDown = type.GetMethod("GetKeyDown", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { _keyCodeType }, null);
				_mousePosition = type.GetProperty("mousePosition", BindingFlags.Static | BindingFlags.Public);
				_available = _getKeyDown != null && _mousePosition != null;
				if (_available)
				{
					KLog.Line("InputCompat resolved against UnityEngine.CoreModule.");
				}
				else
				{
					KLog.Warn("InputCompat: GetKeyDown or mousePosition not found.");
				}
			}
			catch (Exception ex)
			{
				KLog.Warn("InputCompat resolve failed: " + ex.Message);
			}
		}
	}
	internal sealed class KeyboundBinding
	{
		public int PlayerID;

		public string CardName;

		public CardInfo Card;

		public int Key;

		public KeyboundEffectDef Def;

		public float ReadyAt;

		public float LockoutDuration;

		public bool IsReady()
		{
			return Time.time >= ReadyAt;
		}

		public float CooldownFill()
		{
			if (IsReady())
			{
				return 0f;
			}
			float num = ReadyAt - Time.time;
			if (LockoutDuration <= 0f)
			{
				return 1f;
			}
			return Mathf.Clamp01(num / LockoutDuration);
		}

		public void ArmInitialDelay()
		{
			LockoutDuration = Def.InitialDelay;
			ReadyAt = Time.time + Def.InitialDelay;
		}

		public void ArmCooldown()
		{
			LockoutDuration = Def.Cooldown;
			ReadyAt = Time.time + Def.Cooldown;
		}
	}
	internal static class KeyboundCardRegistry
	{
		private static readonly Dictionary<string, KeyboundEffectDef> Effects = new Dictionary<string, KeyboundEffectDef>();

		internal static void Register(KeyboundEffectDef def)
		{
			Effects[def.CardName] = def;
			KLog.Line($"Registered keybound effect '{def.CardName}' (delay={def.InitialDelay}s, cd={def.Cooldown}s).");
		}

		internal static bool IsKeybound(string cardName)
		{
			if (!string.IsNullOrEmpty(cardName))
			{
				return Effects.ContainsKey(cardName);
			}
			return false;
		}

		internal static bool TryGet(string cardName, out KeyboundEffectDef def)
		{
			return Effects.TryGetValue(cardName, out def);
		}

		internal static void RegisterBuiltInEffects()
		{
			Register(TeleportEffect.Def);
		}
	}
	internal sealed class KeyboundEffectDef
	{
		public string CardName;

		public float InitialDelay;

		public float Cooldown;

		public Func<Player, bool> Activate;
	}
	internal static class PickPhaseHelper
	{
		private static readonly FieldInfo s_isPlayingField = AccessTools.Field(typeof(CardChoice), "isPlaying");

		private static readonly FieldInfo s_picksField = AccessTools.Field(typeof(CardChoice), "picks");

		private static readonly FieldInfo s_spawnedCardsField = AccessTools.Field(typeof(CardChoice), "spawnedCards");

		private static readonly MethodInfo s_rpca_donePicking = AccessTools.Method(typeof(CardChoice), "RPCA_DonePicking", (Type[])null, (Type[])null);

		internal static void EndPickPhase()
		{
			KLog.Section("EndPickPhase");
			CardChoice instance = CardChoice.instance;
			if ((Object)(object)instance == (Object)null)
			{
				KLog.Error("CardChoice.instance is null.");
				return;
			}
			((MonoBehaviour)instance).StopAllCoroutines();
			CleanupSpawnedDraftCards(instance);
			if (s_isPlayingField != null)
			{
				s_isPlayingField.SetValue(instance, false);
			}
			if (s_picksField != null)
			{
				s_picksField.SetValue(instance, 0);
			}
			if (s_rpca_donePicking == null)
			{
				instance.IsPicking = false;
			}
			else
			{
				try
				{
					s_rpca_donePicking.Invoke(instance, null);
				}
				catch (Exception ex)
				{
					KLog.Error("RPCA_DonePicking failed: " + ex.Message);
					instance.IsPicking = false;
				}
			}
			KLog.Line($"Pick ended. IsPicking={instance.IsPicking}");
		}

		internal static void RestorePickState(int pickerID, CardInfo card)
		{
			CardChoice instance = CardChoice.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				((MonoBehaviour)instance).StopAllCoroutines();
				instance.pickrID = pickerID;
				if (s_isPlayingField != null)
				{
					s_isPlayingField.SetValue(instance, false);
				}
				instance.IsPicking = true;
				if ((Object)(object)card != (Object)null)
				{
					ApplyCardStats componentInChildren = ((Component)card).GetComponentInChildren<ApplyCardStats>();
					AccessTools.Field(typeof(ApplyCardStats), "done")?.SetValue(componentInChildren, false);
				}
				ResetSpawnedDoneFlags(instance);
				KLog.Line($"Restored pick state for picker {pickerID}.");
			}
		}

		private static void ResetSpawnedDoneFlags(CardChoice cc)
		{
			if (!(s_spawnedCardsField?.GetValue(cc) is IList list))
			{
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(ApplyCardStats), "done");
			foreach (object item in list)
			{
				GameObject val = (GameObject)((item is GameObject) ? item : null);
				if (val != null)
				{
					ApplyCardStats componentInChildren = val.GetComponentInChildren<ApplyCardStats>();
					if ((Object)(object)componentInChildren != (Object)null)
					{
						fieldInfo?.SetValue(componentInChildren, false);
					}
				}
			}
		}

		private static void CleanupSpawnedDraftCards(CardChoice cc)
		{
			if (!(s_spawnedCardsField?.GetValue(cc) is IList list))
			{
				return;
			}
			for (int num = list.Count - 1; num >= 0; num--)
			{
				object? obj = list[num];
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				if (val != null && (Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
			list.Clear();
		}
	}
}
namespace Keybound.Compat
{
	internal static class DeckBuilderBridge
	{
		private static Type _deckManagerType;

		private static MethodInfo _consumeCard;

		private static MethodInfo _getRemaining;

		private static Type _networkSyncType;

		private static MethodInfo _broadcastRemaining;

		private static bool _resolved;

		internal static bool IsAvailable
		{
			get
			{
				Resolve();
				return _consumeCard != null;
			}
		}

		internal static void ConsumeCard(int playerID, CardInfo card)
		{
			Resolve();
			if (_consumeCard == null || (Object)(object)card == (Object)null)
			{
				return;
			}
			try
			{
				_consumeCard.Invoke(null, new object[2] { playerID, card });
				KLog.Line($"Consumed '{card.cardName}' from runtime deck (player {playerID}).");
				BroadcastRemaining(playerID);
			}
			catch (Exception ex)
			{
				KLog.Warn("DeckBuilder ConsumeCard failed: " + ex.Message);
			}
		}

		private static void BroadcastRemaining(int playerID)
		{
			if (_broadcastRemaining == null || _getRemaining == null)
			{
				return;
			}
			try
			{
				int num = (int)_getRemaining.Invoke(null, new object[1] { playerID });
				if (num >= 0)
				{
					_broadcastRemaining.Invoke(null, new object[2] { playerID, num });
				}
			}
			catch (Exception ex)
			{
				KLog.Warn("DeckBuilder broadcast failed: " + ex.Message);
			}
		}

		private static void Resolve()
		{
			if (_resolved)
			{
				return;
			}
			_resolved = true;
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "DeckBuilder");
				if (assembly == null)
				{
					KLog.Line("DeckBuilder not installed — runtime deck consumption skipped.");
					return;
				}
				_deckManagerType = assembly.GetType("DeckBuilder.Data.DeckManager");
				if (!(_deckManagerType == null))
				{
					_consumeCard = _deckManagerType.GetMethod("ConsumeCard", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
					{
						typeof(int),
						typeof(CardInfo)
					}, null);
					_getRemaining = _deckManagerType.GetMethod("GetRemainingCount", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(int) }, null);
					_networkSyncType = assembly.GetType("DeckBuilder.Networking.DeckNetworkSync");
					_broadcastRemaining = _networkSyncType?.GetMethod("BroadcastRemainingCount", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
					{
						typeof(int),
						typeof(int)
					}, null);
				}
			}
			catch (Exception ex)
			{
				KLog.Warn("DeckBuilder bridge resolve failed: " + ex.Message);
			}
		}
	}
}
namespace Keybound.Cards
{
	internal static class CardArtLoader
	{
		private static readonly Dictionary<string, GameObject> Cache = new Dictionary<string, GameObject>();

		private static string AssetsDirectory => Path.Combine(Plugin.PluginDirectory, "assets");

		internal static GameObject Load(string fileName)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_010f: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(fileName))
			{
				return null;
			}
			if (Cache.TryGetValue(fileName, out var value) && (Object)(object)value != (Object)null)
			{
				KLog.Line("CardArtLoader: Returning cached art for '" + fileName + "'.");
				return value;
			}
			string text = Path.Combine(AssetsDirectory, fileName);
			KLog.Line("CardArtLoader: Loading '" + fileName + "' from " + text);
			if (!File.Exists(text))
			{
				KLog.Warn("CardArtLoader: Card art not found: " + text);
				return null;
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, array))
			{
				KLog.Warn("CardArtLoader: Failed to decode card art: " + text);
				Object.Destroy((Object)(object)val);
				return null;
			}
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			Sprite sprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
			GameObject val2 = new GameObject("KeyboundCardArt_" + fileName);
			Object.DontDestroyOnLoad((Object)(object)val2);
			RectTransform obj = val2.AddComponent<RectTransform>();
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			obj.offsetMin = Vector2.zero;
			obj.offsetMax = Vector2.zero;
			((Transform)obj).localPosition = Vector3.up * 10000f;
			Image obj2 = val2.AddComponent<Image>();
			obj2.sprite = sprite;
			obj2.preserveAspect = true;
			((Graphic)obj2).raycastTarget = false;
			Cache[fileName] = val2;
			KLog.Line($"CardArtLoader: Loaded {((Texture)val).width}x{((Texture)val).height} from {text}");
			return val2;
		}
	}
	internal static class KeyboundCardRegistrar
	{
		internal static void RegisterAll()
		{
			KLog.Section("KeyboundCardRegistrar — RegisterAll");
			KeyboundCardRegistry.RegisterBuiltInEffects();
			CustomCard.BuildCard<TeleportCard>((Action<CardInfo>)delegate(CardInfo ci)
			{
				KLog.Line("Registered keybound card: " + ci.cardName);
			});
		}
	}
	public class TeleportCard : CustomCard
	{
		public const string CardDisplayName = "Teleport";

		protected override string GetTitle()
		{
			return "Teleport";
		}

		protected override string GetDescription()
		{
			return "[Keybound] Press your bound key to teleport to your cursor.\nBecomes available 10s after the round starts. Cooldown: 15s.";
		}

		protected override CardInfoStat[] GetStats()
		{
			return Array.Empty<CardInfoStat>();
		}

		protected override Rarity GetRarity()
		{
			return (Rarity)2;
		}

		protected override GameObject GetCardArt()
		{
			return CardArtLoader.Load("Teleport.png");
		}

		protected override CardThemeColorType GetTheme()
		{
			return (CardThemeColorType)2;
		}

		public override string GetModName()
		{
			return "Keybound";
		}

		public override void OnAddCard(Player player, Gun gun, GunAmmo gunAmmo, CharacterData data, HealthHandler health, Gravity gravity, Block block, CharacterStatModifiers characterStats)
		{
		}
	}
}

ShieldsMod.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using InfoOverhaul.Delta;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using RarityLib.Utils;
using ShieldsMod.Cards;
using ShieldsMod.Lifesteal;
using ShieldsMod.Networking;
using ShieldsMod.Poison;
using ShieldsMod.Resistance;
using ShieldsMod.Shield;
using ShieldsMod.Stun;
using UnboundLib;
using UnboundLib.Cards;
using UnboundLib.GameModes;
using UnboundLib.Networking;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: AssemblyCompany("ShieldsMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+146ac727a7fc6b83f382d57f53cce40478349c58")]
[assembly: AssemblyProduct("Shields Mod for ROUNDS")]
[assembly: AssemblyTitle("ShieldsMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 ShieldsMod
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("ShieldsMod", "Shields Mod for ROUNDS", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		internal static string PluginDirectory { get; private set; }

		private void Awake()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? "";
			SLog.Section("Plugin Awake");
			SLog.Line("PluginDirectory = " + PluginDirectory);
			new Harmony("ShieldsMod").PatchAll();
			((Component)this).gameObject.AddComponent<ShieldManager>();
			((Component)this).gameObject.AddComponent<PoisonResistanceManager>();
			((Component)this).gameObject.AddComponent<StunResistanceManager>();
			((Component)this).gameObject.AddComponent<LifestealResistanceManager>();
			SLog.Line("Plugin ShieldsMod loaded.");
		}

		private void Start()
		{
			ShieldCardRegistrar.RegisterAll();
			PoisonCardRegistrar.RegisterAll();
			StunCardRegistrar.RegisterAll();
			LifestealCardRegistrar.RegisterAll();
		}
	}
	internal static class SLog
	{
		private const string Sep = "=====================";

		public static void Section(string title)
		{
			Plugin.Logger.LogInfo((object)"=====================");
			Plugin.Logger.LogInfo((object)("[ShieldsMod] " + title));
			Plugin.Logger.LogInfo((object)"=====================");
		}

		public static void Line(string message)
		{
			Plugin.Logger.LogInfo((object)("[ShieldsMod] " + message));
		}

		public static void Warn(string message)
		{
			Plugin.Logger.LogWarning((object)("[ShieldsMod] " + message));
		}

		public static void Error(string message)
		{
			Plugin.Logger.LogError((object)("[ShieldsMod] " + message));
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "ShieldsMod";

		public const string PLUGIN_NAME = "Shields Mod for ROUNDS";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace ShieldsMod.Stun
{
	internal static class StunHandRebuild
	{
		private static Dictionary<string, int> _levelByCardName;

		internal static void RegisterTier(string cardName, int level)
		{
			if (!string.IsNullOrEmpty(cardName) && level >= 1 && level <= 3)
			{
				if (_levelByCardName == null)
				{
					_levelByCardName = new Dictionary<string, int>(StringComparer.Ordinal);
				}
				_levelByCardName[cardName] = level;
			}
		}

		internal static float ComputeReductionFromHand(IEnumerable<CardInfo> cards, CardInfo exclude = null)
		{
			return ResistanceTierLogic.ComputeFromHand(cards, _levelByCardName, exclude);
		}

		internal static void RebuildForPlayer(int playerID)
		{
			StunResistanceManager.instance?.RebuildForPlayer(playerID);
		}
	}
	public class StunResistanceManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <OnBattleStart>d__3 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

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

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

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

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

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				if ((Object)(object)PlayerManager.instance == (Object)null)
				{
					return false;
				}
				foreach (Player player in PlayerManager.instance.players)
				{
					if ((Object)(object)player != (Object)null)
					{
						instance?.RebuildForPlayer(player.playerID);
					}
				}
				return false;
			}

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

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

		public static StunResistanceManager instance;

		private readonly Dictionary<int, float> _reductionByPlayer = new Dictionary<int, float>();

		private void Awake()
		{
			instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			GameModeManager.AddHook("BattleStart", (Func<IGameModeHandler, IEnumerator>)OnBattleStart);
			SLog.Section("StunResistanceManager — Awake");
		}

		[IteratorStateMachine(typeof(<OnBattleStart>d__3))]
		private static IEnumerator OnBattleStart(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnBattleStart>d__3(0);
		}

		private void OnDestroy()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		public float GetReduction(int playerID)
		{
			if (!_reductionByPlayer.TryGetValue(playerID, out var value))
			{
				return 0f;
			}
			return value;
		}

		public float GetReductionPercent(int playerID)
		{
			return GetReduction(playerID) * 100f;
		}

		public void RebuildForPlayer(int playerID)
		{
			if (!((Object)(object)PlayerManager.instance == (Object)null))
			{
				Player val = PlayerManager.instance.players.Find((Player p) => p.playerID == playerID);
				if (val?.data?.currentCards != null)
				{
					float num = StunHandRebuild.ComputeReductionFromHand(val.data.currentCards);
					_reductionByPlayer[playerID] = num;
					SLog.Line($"StunResistance rebuild player={playerID} reduction={num * 100f:F0}%");
				}
			}
		}

		public float ApplyResistance(int playerID, float rawDuration, out float resistedAmount)
		{
			float reduction = GetReduction(playerID);
			resistedAmount = rawDuration * reduction;
			return rawDuration - resistedAmount;
		}
	}
}
namespace ShieldsMod.Shield
{
	internal static class ShieldHandRebuild
	{
		private readonly struct ShieldTier
		{
			public readonly float FirstShieldMax;

			public readonly float StackMultiplier;

			public ShieldTier(float firstShieldMax, float stackMultiplier)
			{
				FirstShieldMax = firstShieldMax;
				StackMultiplier = stackMultiplier;
			}
		}

		private static Dictionary<string, ShieldTier> _tierByCardName;

		internal static void RegisterTier(CardInfo card, float firstShieldMax, float stackMultiplier)
		{
			if (!((Object)(object)card == (Object)null) && !string.IsNullOrEmpty(card.cardName))
			{
				if (_tierByCardName == null)
				{
					_tierByCardName = new Dictionary<string, ShieldTier>(StringComparer.Ordinal);
				}
				_tierByCardName[card.cardName] = new ShieldTier(firstShieldMax, stackMultiplier);
			}
		}

		internal static float ComputeMaxFromHandExcluding(IEnumerable<CardInfo> cards, CardInfo exclude)
		{
			return ComputeMaxFromCards(cards, exclude);
		}

		internal static void RebuildForPlayer(int playerID)
		{
			if ((Object)(object)ShieldManager.instance == (Object)null || (Object)(object)PlayerManager.instance == (Object)null)
			{
				return;
			}
			Player val = PlayerManager.instance.players.Find((Player p) => p.playerID == playerID);
			if (val?.data?.currentCards != null)
			{
				ShieldState orCreateShield = ShieldManager.instance.GetOrCreateShield(playerID);
				float max = orCreateShield.Max;
				float num = ComputeMaxFromCards(val.data.currentCards);
				if (num <= 0f)
				{
					orCreateShield.Max = 0f;
					orCreateShield.Current = 0f;
				}
				else
				{
					orCreateShield.Max = num;
					orCreateShield.Current = Mathf.Min(orCreateShield.Current, orCreateShield.Max);
				}
				ShieldManager.instance.RefreshVisual(playerID);
				SLog.Line($"ShieldHandRebuild player={playerID} max {max:F0} -> {orCreateShield.Max:F0} current={orCreateShield.Current:F0}");
			}
		}

		private static float ComputeMaxFromCards(IEnumerable<CardInfo> cards, CardInfo exclude = null)
		{
			if (_tierByCardName == null || cards == null)
			{
				return 0f;
			}
			float num = 0f;
			bool flag = false;
			foreach (CardInfo card in cards)
			{
				if ((Object)(object)card == (Object)null || ((Object)(object)exclude != (Object)null && ((Object)card).name == ((Object)exclude).name))
				{
					continue;
				}
				string cardName = card.cardName;
				if (string.IsNullOrEmpty(cardName) && (Object)(object)card.sourceCard != (Object)null)
				{
					cardName = card.sourceCard.cardName;
				}
				if (!string.IsNullOrEmpty(cardName) && _tierByCardName.TryGetValue(cardName, out var value))
				{
					if (!flag)
					{
						num = value.FirstShieldMax;
						flag = true;
					}
					else
					{
						num *= value.StackMultiplier;
					}
				}
			}
			if (!flag)
			{
				return 0f;
			}
			return num;
		}
	}
	public class ShieldManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <OnBattleStart>d__6 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

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

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

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

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

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				instance?.ResetAllForBattle();
				return false;
			}

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

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

		[CompilerGenerated]
		private sealed class <OnGameStart>d__8 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

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

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

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

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

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				instance?.CleanupOrphanedAttachments();
				return false;
			}

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

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

		[CompilerGenerated]
		private sealed class <OnPointEnd>d__7 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

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

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

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

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

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				instance?.CleanupOrphanedAttachments();
				return false;
			}

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

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

		public static ShieldManager instance;

		private readonly Dictionary<int, ShieldState> _shields = new Dictionary<int, ShieldState>();

		private readonly Dictionary<int, ShieldVisual> _visuals = new Dictionary<int, ShieldVisual>();

		private readonly Dictionary<int, ShieldParryTrigger> _parryTriggers = new Dictionary<int, ShieldParryTrigger>();

		private void Awake()
		{
			instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			SLog.Section("ShieldManager — Awake");
			GameModeManager.AddHook("BattleStart", (Func<IGameModeHandler, IEnumerator>)OnBattleStart);
			GameModeManager.AddHook("PointEnd", (Func<IGameModeHandler, IEnumerator>)OnPointEnd);
			GameModeManager.AddHook("GameStart", (Func<IGameModeHandler, IEnumerator>)OnGameStart);
		}

		private void OnDestroy()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		[IteratorStateMachine(typeof(<OnBattleStart>d__6))]
		private static IEnumerator OnBattleStart(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnBattleStart>d__6(0);
		}

		[IteratorStateMachine(typeof(<OnPointEnd>d__7))]
		private static IEnumerator OnPointEnd(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnPointEnd>d__7(0);
		}

		[IteratorStateMachine(typeof(<OnGameStart>d__8))]
		private static IEnumerator OnGameStart(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnGameStart>d__8(0);
		}

		public void ResetAllForBattle()
		{
			SLog.Section("ShieldManager — ResetAllForBattle");
			if ((Object)(object)PlayerManager.instance == (Object)null)
			{
				SLog.Warn("PlayerManager.instance is null.");
				return;
			}
			foreach (Player player in PlayerManager.instance.players)
			{
				if (!((Object)(object)player == (Object)null))
				{
					ShieldHandRebuild.RebuildForPlayer(player.playerID);
					ShieldState orCreateShield = GetOrCreateShield(player.playerID);
					if (orCreateShield.HasShield)
					{
						orCreateShield.ResetToFull();
					}
					else
					{
						orCreateShield.Current = 0f;
					}
					EnsureAttachments(player, orCreateShield);
					RefreshVisual(player.playerID);
					SLog.Line($"player={player.playerID} shield={orCreateShield.Current}/{orCreateShield.Max}");
				}
			}
		}

		public ShieldState GetOrCreateShield(int playerID)
		{
			if (!_shields.TryGetValue(playerID, out var value))
			{
				value = new ShieldState();
				_shields[playerID] = value;
			}
			return value;
		}

		public ShieldState GetShield(int playerID)
		{
			return GetOrCreateShield(playerID);
		}

		public bool TryAbsorbFull(int playerID, float damageAmount, out bool depleted)
		{
			depleted = false;
			ShieldState orCreateShield = GetOrCreateShield(playerID);
			if (!orCreateShield.IsActive || damageAmount <= 0f)
			{
				return false;
			}
			if (damageAmount >= orCreateShield.Current)
			{
				orCreateShield.Current = 0f;
				depleted = true;
			}
			else
			{
				orCreateShield.Current -= damageAmount;
			}
			RefreshVisual(playerID);
			return true;
		}

		public void RefreshVisual(int playerID)
		{
			if (_visuals.TryGetValue(playerID, out var value) && (Object)(object)value != (Object)null)
			{
				value.Refresh();
			}
			if (_parryTriggers.TryGetValue(playerID, out var value2) && (Object)(object)value2 != (Object)null)
			{
				value2.UpdateEnabled();
			}
		}

		private void EnsureAttachments(Player player, ShieldState state)
		{
			//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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			int playerID = player.playerID;
			if (!_visuals.TryGetValue(playerID, out var value) || (Object)(object)value == (Object)null)
			{
				GameObject val = new GameObject($"ShieldVisual_P{playerID}");
				val.transform.SetParent(((Component)player).transform, false);
				value = val.AddComponent<ShieldVisual>();
				value.Init(player, state);
				_visuals[playerID] = value;
			}
			else
			{
				value.SetState(state);
				value.Refresh();
			}
			if (!_parryTriggers.TryGetValue(playerID, out var value2) || (Object)(object)value2 == (Object)null)
			{
				GameObject val2 = new GameObject($"ShieldParry_P{playerID}");
				val2.transform.SetParent(((Component)player).transform, false);
				value2 = val2.AddComponent<ShieldParryTrigger>();
				float radius = ShieldVisual.GetBodyRadius(player) * 1.44f;
				value2.Init(player, state, radius);
				_parryTriggers[playerID] = value2;
			}
			else
			{
				value2.SetState(state);
				value2.UpdateEnabled();
			}
		}

		private void CleanupOrphanedAttachments()
		{
			List<int> list = new List<int>();
			foreach (KeyValuePair<int, ShieldVisual> visual in _visuals)
			{
				if ((Object)(object)visual.Value == (Object)null)
				{
					list.Add(visual.Key);
				}
			}
			foreach (int item in list)
			{
				_visuals.Remove(item);
			}
			List<int> list2 = new List<int>();
			foreach (KeyValuePair<int, ShieldParryTrigger> parryTrigger in _parryTriggers)
			{
				if ((Object)(object)parryTrigger.Value == (Object)null)
				{
					list2.Add(parryTrigger.Key);
				}
			}
			foreach (int item2 in list2)
			{
				_parryTriggers.Remove(item2);
			}
		}
	}
	public class ShieldParryTrigger : MonoBehaviour
	{
		private Player _owner;

		private Block _block;

		private CircleCollider2D _trigger;

		private ShieldState _state;

		private readonly HashSet<int> _recentlyDeflected = new HashSet<int>();

		public void Init(Player owner, ShieldState state, float radius)
		{
			_owner = owner;
			_state = state;
			_block = ((Component)owner).GetComponent<Block>();
			_trigger = ((Component)this).gameObject.AddComponent<CircleCollider2D>();
			((Collider2D)_trigger).isTrigger = true;
			_trigger.radius = radius;
			Rigidbody2D obj = ((Component)this).gameObject.AddComponent<Rigidbody2D>();
			obj.bodyType = (RigidbodyType2D)1;
			obj.simulated = true;
			UpdateEnabled();
		}

		public void SetState(ShieldState state)
		{
			_state = state;
		}

		public void SetRadius(float worldRadius)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_owner == (Object)null) && !((Object)(object)_trigger == (Object)null))
			{
				float num = Mathf.Max(((Component)_owner).transform.localScale.x, 0.01f);
				_trigger.radius = worldRadius / num;
			}
		}

		public void UpdateEnabled()
		{
			if ((Object)(object)_trigger != (Object)null)
			{
				((Behaviour)_trigger).enabled = _state != null && _state.IsActive;
			}
		}

		private void LateUpdate()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_owner == (Object)null))
			{
				((Component)this).transform.position = ((Component)_owner).transform.position;
				float bodyRadius = ShieldVisual.GetBodyRadius(_owner);
				SetRadius(bodyRadius * 1.44f);
				UpdateEnabled();
			}
		}

		private void OnTriggerEnter2D(Collider2D other)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_owner == (Object)null || (Object)(object)_block == (Object)null || _state == null || !_state.IsActive || !_block.IsBlocking())
			{
				return;
			}
			ProjectileHit val = ((Component)other).GetComponent<ProjectileHit>() ?? ((Component)other).GetComponentInParent<ProjectileHit>();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			PhotonView component = ((Component)val).GetComponent<PhotonView>();
			if ((Object)(object)component == (Object)null || !component.IsMine)
			{
				return;
			}
			int instanceID = ((Object)((Component)val).gameObject).GetInstanceID();
			if (!_recentlyDeflected.Contains(instanceID) && IsEnemyProjectile(val))
			{
				Vector3 position = ((Component)val).transform.position;
				Vector3 val2 = ((Component)val).transform.forward;
				if (((Vector3)(ref val2)).sqrMagnitude < 0.001f)
				{
					Vector3 val3 = position - ((Component)_owner).transform.position;
					val2 = ((Vector3)(ref val3)).normalized;
				}
				_recentlyDeflected.Add(instanceID);
				_block.DoBlock(((Component)val).gameObject, val2, position);
				SLog.Line($"Outer parry player={_owner.playerID} projectile={((Object)((Component)val).gameObject).name}");
			}
		}

		private bool IsEnemyProjectile(ProjectileHit projHit)
		{
			Player val = projHit.ownPlayer;
			if ((Object)(object)val == (Object)null)
			{
				SpawnedAttack component = ((Component)projHit).GetComponent<SpawnedAttack>();
				if ((Object)(object)component != (Object)null)
				{
					val = component.spawner;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			if (val.playerID != _owner.playerID)
			{
				return (Object)(object)((Component)val).transform.root != (Object)(object)((Component)_owner).transform.root;
			}
			return false;
		}

		private void OnTriggerExit2D(Collider2D other)
		{
			ProjectileHit val = ((Component)other).GetComponent<ProjectileHit>() ?? ((Component)other).GetComponentInParent<ProjectileHit>();
			if ((Object)(object)val != (Object)null)
			{
				_recentlyDeflected.Remove(((Object)((Component)val).gameObject).GetInstanceID());
			}
		}
	}
	public class ShieldState
	{
		public const float DefaultMax = 100f;

		public float Max;

		public float Current;

		public const float BubbleAlpha = 0.05f;

		public bool HasShield => Max > 0f;

		public float Percent
		{
			get
			{
				if (!(Max > 0f))
				{
					return 0f;
				}
				return Current / Max;
			}
		}

		public bool IsActive => Current > 0f;

		public void ResetToFull()
		{
			Current = Max;
		}

		public Color GetBubbleColor(float alpha = 0.05f)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			float percent = Percent;
			Color val = default(Color);
			if (percent > 0.65f)
			{
				((Color)(ref val))..ctor(0.2f, 0.9f, 0.25f);
			}
			else if (percent > 0.35f)
			{
				((Color)(ref val))..ctor(0.95f, 0.85f, 0.15f);
			}
			else
			{
				((Color)(ref val))..ctor(0.95f, 0.2f, 0.15f);
			}
			return new Color(val.r, val.g, val.b, alpha);
		}
	}
	public class ShieldVisual : MonoBehaviour
	{
		public const float SizeMultiplier = 1.44f;

		private const int CircleTexSize = 128;

		private Player _player;

		private SpriteRenderer _sprite;

		private ShieldState _state;

		public static Sprite SharedCircleSprite { get; private set; }

		public void Init(Player player, ShieldState state)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			_player = player;
			_state = state;
			if ((Object)(object)SharedCircleSprite == (Object)null)
			{
				SharedCircleSprite = CreateCircleSprite(128);
			}
			GameObject val = new GameObject("ShieldBubbleSprite");
			val.transform.SetParent(((Component)this).transform, false);
			_sprite = val.AddComponent<SpriteRenderer>();
			_sprite.sprite = SharedCircleSprite;
			((Renderer)_sprite).sortingOrder = -1;
			int num = SortingLayer.NameToID("Player" + (player.playerID + 1));
			if (num != 0)
			{
				((Renderer)_sprite).sortingLayerID = num;
			}
			player.data.SetWobbleObjectChild(((Component)this).transform);
			Refresh();
		}

		public void SetState(ShieldState state)
		{
			_state = state;
		}

		public void Refresh()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_sprite == (Object)null || (Object)(object)_player == (Object)null || _state == null)
			{
				return;
			}
			if (!_state.IsActive)
			{
				((Renderer)_sprite).enabled = false;
				return;
			}
			((Renderer)_sprite).enabled = true;
			_sprite.color = _state.GetBubbleColor();
			float num = GetBodyRadius(_player) * 2f * 1.44f;
			Bounds bounds = _sprite.sprite.bounds;
			float x = ((Bounds)(ref bounds)).size.x;
			if (x > 0.0001f)
			{
				((Component)_sprite).transform.localScale = Vector3.one * (num / x);
			}
		}

		public static float GetBodyRadius(Player player)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return 0.5f;
			}
			CircleCollider2D val = ((Component)player).GetComponent<CircleCollider2D>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)player).GetComponentInChildren<CircleCollider2D>();
			}
			return (((Object)(object)val != (Object)null) ? val.radius : 0.5f) * ((Component)player).transform.localScale.x;
		}

		private void LateUpdate()
		{
			if (_state != null && _state.IsActive)
			{
				Refresh();
			}
		}

		private static Sprite CreateCircleSprite(int size)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
			((Texture)val).filterMode = (FilterMode)1;
			float num = (float)(size - 1) * 0.5f;
			float num2 = num - 1f;
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num3 = (float)j - num;
					float num4 = (float)i - num;
					float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4);
					float num6 = ((num5 <= num2) ? 1f : Mathf.Clamp01(1f - (num5 - num2)));
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num6));
				}
			}
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), (float)size);
		}
	}
}
namespace ShieldsMod.Resistance
{
	internal static class ResistanceTierLogic
	{
		public const float StackBonus = 0.05f;

		public const float Lv2UpgradeThreshold = 0.5f;

		public const float Lv3UpgradeThreshold = 0.75f;

		private static readonly float[] FirstReductionByLevel = new float[4] { 0f, 0.25f, 0.5f, 0.75f };

		internal static float GetFirstReduction(int level)
		{
			if (level < 1 || level > 3)
			{
				return 0f;
			}
			return FirstReductionByLevel[level];
		}

		internal static float ComputeFromHand(IEnumerable<CardInfo> cards, IReadOnlyDictionary<string, int> tierByCardName, CardInfo exclude = null)
		{
			if (tierByCardName == null || cards == null)
			{
				return 0f;
			}
			float num = 0f;
			bool flag = false;
			foreach (CardInfo card in cards)
			{
				if (!((Object)(object)card == (Object)null) && (!((Object)(object)exclude != (Object)null) || !(((Object)card).name == ((Object)exclude).name)) && TryGetLevel(card, tierByCardName, out var level))
				{
					if (!flag)
					{
						num = GetFirstReduction(level);
						flag = true;
					}
					else
					{
						num = ApplyStacking(num, level, out var _);
					}
				}
			}
			if (!flag)
			{
				return 0f;
			}
			return ClampReduction(num);
		}

		internal static float ApplyCard(float currentReduction, int level, out float? healthMultiplier)
		{
			healthMultiplier = null;
			if (!(currentReduction > 0.0001f))
			{
				return ClampReduction(GetFirstReduction(level));
			}
			return ClampReduction(ApplyStacking(currentReduction, level, out healthMultiplier));
		}

		internal static void ApplyHealthBonus(CharacterData data, float multiplier)
		{
			if (!((Object)(object)data == (Object)null) && !(multiplier <= 1.0001f))
			{
				float num = ((data.maxHealth > 0f) ? (data.health / data.maxHealth) : 1f);
				data.maxHealth *= multiplier;
				data.health = Mathf.Clamp(data.maxHealth * num, 1f, data.maxHealth);
			}
		}

		private static float ApplyStacking(float current, int level, out float? healthMultiplier)
		{
			healthMultiplier = null;
			switch (level)
			{
			case 1:
				return current + 0.05f;
			case 2:
				if (current < 0.5f)
				{
					return 0.5f;
				}
				healthMultiplier = 1.1f;
				return current + 0.05f;
			case 3:
				if (current < 0.75f)
				{
					return 0.75f;
				}
				healthMultiplier = 1.25f;
				return current + 0.05f;
			default:
				return current;
			}
		}

		private static bool TryGetLevel(CardInfo card, IReadOnlyDictionary<string, int> tierByCardName, out int level)
		{
			level = 0;
			if ((Object)(object)card == (Object)null)
			{
				return false;
			}
			string cardName = card.cardName;
			if (string.IsNullOrEmpty(cardName) && (Object)(object)card.sourceCard != (Object)null)
			{
				cardName = card.sourceCard.cardName;
			}
			if (!string.IsNullOrEmpty(cardName))
			{
				return tierByCardName.TryGetValue(cardName, out level);
			}
			return false;
		}

		private static float ClampReduction(float value)
		{
			return Mathf.Clamp01(value);
		}
	}
}
namespace ShieldsMod.Poison
{
	internal static class PoisonDamageDetector
	{
		public static bool IsPoisonDamage(Color blinkColor, GameObject damagingWeapon)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)damagingWeapon != (Object)null)
			{
				if ((Object)(object)damagingWeapon.GetComponentInChildren<RayHitPoison>() != (Object)null)
				{
					return true;
				}
				Transform root = damagingWeapon.transform.root;
				if ((Object)(object)root != (Object)null && (Object)(object)((Component)root).GetComponentInChildren<RayHitPoison>() != (Object)null)
				{
					return true;
				}
			}
			if (blinkColor.g > 0.35f && blinkColor.g >= blinkColor.r)
			{
				return blinkColor.g >= blinkColor.b;
			}
			return false;
		}
	}
	internal static class PoisonHandRebuild
	{
		private static Dictionary<string, int> _levelByCardName;

		internal static void RegisterTier(string cardName, int level)
		{
			if (!string.IsNullOrEmpty(cardName) && level >= 1 && level <= 3)
			{
				if (_levelByCardName == null)
				{
					_levelByCardName = new Dictionary<string, int>(StringComparer.Ordinal);
				}
				_levelByCardName[cardName] = level;
			}
		}

		internal static float ComputeReductionFromHand(IEnumerable<CardInfo> cards, CardInfo exclude = null)
		{
			return ResistanceTierLogic.ComputeFromHand(cards, _levelByCardName, exclude);
		}

		internal static void RebuildForPlayer(int playerID)
		{
			PoisonResistanceManager.instance?.RebuildForPlayer(playerID);
		}
	}
	public class PoisonResistanceManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <OnBattleStart>d__3 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

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

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

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

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

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				if ((Object)(object)PlayerManager.instance == (Object)null)
				{
					return false;
				}
				foreach (Player player in PlayerManager.instance.players)
				{
					if ((Object)(object)player != (Object)null)
					{
						instance?.RebuildForPlayer(player.playerID);
					}
				}
				return false;
			}

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

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

		public static PoisonResistanceManager instance;

		private readonly Dictionary<int, float> _reductionByPlayer = new Dictionary<int, float>();

		private void Awake()
		{
			instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			GameModeManager.AddHook("BattleStart", (Func<IGameModeHandler, IEnumerator>)OnBattleStart);
			SLog.Section("PoisonResistanceManager — Awake");
		}

		[IteratorStateMachine(typeof(<OnBattleStart>d__3))]
		private static IEnumerator OnBattleStart(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnBattleStart>d__3(0);
		}

		private void OnDestroy()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		public float GetReduction(int playerID)
		{
			if (!_reductionByPlayer.TryGetValue(playerID, out var value))
			{
				return 0f;
			}
			return value;
		}

		public float GetReductionPercent(int playerID)
		{
			return GetReduction(playerID) * 100f;
		}

		public void RebuildForPlayer(int playerID)
		{
			if (!((Object)(object)PlayerManager.instance == (Object)null))
			{
				Player val = PlayerManager.instance.players.Find((Player p) => p.playerID == playerID);
				if (val?.data?.currentCards != null)
				{
					float num = PoisonHandRebuild.ComputeReductionFromHand(val.data.currentCards);
					_reductionByPlayer[playerID] = num;
					SLog.Line($"PoisonResistance rebuild player={playerID} reduction={num * 100f:F0}%");
				}
			}
		}

		public float ApplyResistance(int playerID, float rawDamage, out float resistedAmount)
		{
			float reduction = GetReduction(playerID);
			resistedAmount = rawDamage * reduction;
			return rawDamage - resistedAmount;
		}
	}
}
namespace ShieldsMod.Patches
{
	[HarmonyPatch]
	internal static class CardDeleteRebuildPatch
	{
		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("DeckBuilder.CardDelete.CardDeleteManager");
			if (!(type == null))
			{
				return AccessTools.Method(type, "URPC_SyncDelete", (Type[])null, (Type[])null);
			}
			return null;
		}

		private static bool Prepare()
		{
			bool num = TargetMethod() != null;
			if (!num)
			{
				SLog.Line("CardDeleteRebuildPatch — CardDeleteManager not found; delete hook skipped.");
			}
			return num;
		}

		private static void Postfix(int playerID)
		{
			ShieldHandRebuild.RebuildForPlayer(playerID);
			PoisonHandRebuild.RebuildForPlayer(playerID);
			StunHandRebuild.RebuildForPlayer(playerID);
			LifestealHandRebuild.RebuildForPlayer(playerID);
		}
	}
	[HarmonyPatch(typeof(CharacterStatModifiers), "DealtDamage")]
	internal static class CharacterStatModifiersDealtDamagePatch
	{
		[HarmonyPostfix]
		private static void Postfix(CharacterStatModifiers __instance, Vector2 damage, bool selfDamage, Player damagedPlayer)
		{
			if (selfDamage || (Object)(object)damagedPlayer == (Object)null || __instance.lifeSteal == 0f || (Object)(object)LifestealResistanceManager.instance == (Object)null || LifestealResistanceManager.instance.GetReduction(damagedPlayer.playerID) <= 0f)
			{
				return;
			}
			float num = ((Vector2)(ref damage)).magnitude * __instance.lifeSteal;
			float resistedAmount;
			float num2 = LifestealResistanceManager.instance.ApplyResistance(damagedPlayer.playerID, num, out resistedAmount);
			if (!(resistedAmount <= 0f))
			{
				Player component = ((Component)__instance).GetComponent<Player>();
				if (!((Object)(object)component?.data == (Object)null))
				{
					CharacterData data = component.data;
					data.health -= resistedAmount;
					component.data.health = Mathf.Clamp(component.data.health, 1f, component.data.maxHealth);
					SLog.Section("Lifesteal resistance");
					SLog.Line($"Player {component?.playerID ?? (-1)} would've healed {num:F1} from life steal but healed {num2:F1} instead (victim {damagedPlayer.playerID} resisted {resistedAmount:F1}).");
				}
			}
		}
	}
	[HarmonyPatch(typeof(HealthHandler), "DoDamage")]
	internal static class HealthHandlerDoDamagePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(HealthHandler __instance, ref Vector2 damage, Vector2 position, Color blinkColor, GameObject damagingWeapon, Player damagingPlayer, bool healthRemoval, bool lethal, bool ignoreBlock)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			if (damage == Vector2.zero)
			{
				return true;
			}
			Player component = ((Component)__instance).GetComponent<Player>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			float magnitude = ((Vector2)(ref damage)).magnitude;
			float num = magnitude;
			bool flag = PoisonDamageDetector.IsPoisonDamage(blinkColor, damagingWeapon);
			if (flag && (Object)(object)PoisonResistanceManager.instance != (Object)null && PoisonResistanceManager.instance.GetReduction(component.playerID) > 0f)
			{
				num = PoisonResistanceManager.instance.ApplyResistance(component.playerID, magnitude, out var _);
				if (num > 0f)
				{
					damage = ((Vector2)(ref damage)).normalized * num;
				}
				else
				{
					damage = Vector2.zero;
				}
			}
			if (num <= 0f)
			{
				return false;
			}
			if ((Object)(object)ShieldManager.instance == (Object)null)
			{
				if (flag && magnitude > num)
				{
					LogPoisonPlayerDamage(component.playerID, magnitude, num);
				}
				return true;
			}
			if (!ShieldManager.instance.TryAbsorbFull(component.playerID, num, out var depleted))
			{
				if (flag && magnitude > num)
				{
					LogPoisonPlayerDamage(component.playerID, magnitude, num);
				}
				return true;
			}
			if (flag && magnitude > num)
			{
				LogPoisonShieldDamage(component.playerID, magnitude, num, depleted);
			}
			damage = Vector2.zero;
			if ((Object)(object)component.data?.view != (Object)null && component.data.view.IsMine)
			{
				ShieldNetworkSync.BroadcastShieldHealth(component.playerID, ShieldManager.instance.GetShield(component.playerID).Current);
			}
			return false;
		}

		private static void LogPoisonPlayerDamage(int playerID, float rawAmount, float actualAmount)
		{
			SLog.Section("Poison resistance — player");
			SLog.Line($"Player {playerID} would've taken {rawAmount:F1} poison damage but took {actualAmount:F1} instead.");
		}

		private static void LogPoisonShieldDamage(int playerID, float rawAmount, float actualAmount, bool depleted)
		{
			SLog.Section("Poison resistance — shield");
			SLog.Line($"Player {playerID}'s shield would've taken {rawAmount:F1} poison damage but took {actualAmount:F1} instead (depleted={depleted}).");
		}
	}
	[HarmonyPatch(typeof(StunHandler), "AddStun")]
	internal static class StunHandlerAddStunPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(StunHandler __instance, ref float f)
		{
			if (f <= 0f || (Object)(object)StunResistanceManager.instance == (Object)null)
			{
				return true;
			}
			Player component = ((Component)__instance).GetComponent<Player>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			if (StunResistanceManager.instance.GetReduction(component.playerID) <= 0f)
			{
				return true;
			}
			float num = f;
			f = StunResistanceManager.instance.ApplyResistance(component.playerID, num, out var _);
			if (num > f)
			{
				SLog.Section("Stun resistance");
				SLog.Line($"Player {component.playerID} would've been stunned for {num:F2}s but duration was reduced to {f:F2}s.");
			}
			if (f <= 0f)
			{
				return false;
			}
			return true;
		}
	}
}
namespace ShieldsMod.Networking
{
	public static class ShieldNetworkSync
	{
		public static void BroadcastShieldHealth(int playerID, float current)
		{
			SLog.Line($"BroadcastShieldHealth player={playerID} current={current:F1}");
			NetworkingManager.RPC(typeof(ShieldNetworkSync), "URPC_SetShieldHealth", new object[2] { playerID, current });
		}

		[UnboundRPC]
		public static void URPC_SetShieldHealth(int playerID, float current)
		{
			if (!((Object)(object)ShieldManager.instance == (Object)null))
			{
				ShieldState orCreateShield = ShieldManager.instance.GetOrCreateShield(playerID);
				orCreateShield.Current = Mathf.Clamp(current, 0f, orCreateShield.Max);
				ShieldManager.instance.RefreshVisual(playerID);
				SLog.Line($"URPC_SetShieldHealth player={playerID} current={orCreateShield.Current:F1}");
			}
		}
	}
}
namespace ShieldsMod.Lifesteal
{
	internal static class LifestealHandRebuild
	{
		private static Dictionary<string, int> _levelByCardName;

		internal static void RegisterTier(string cardName, int level)
		{
			if (!string.IsNullOrEmpty(cardName) && level >= 1 && level <= 3)
			{
				if (_levelByCardName == null)
				{
					_levelByCardName = new Dictionary<string, int>(StringComparer.Ordinal);
				}
				_levelByCardName[cardName] = level;
			}
		}

		internal static float ComputeReductionFromHand(IEnumerable<CardInfo> cards, CardInfo exclude = null)
		{
			return ResistanceTierLogic.ComputeFromHand(cards, _levelByCardName, exclude);
		}

		internal static void RebuildForPlayer(int playerID)
		{
			LifestealResistanceManager.instance?.RebuildForPlayer(playerID);
		}
	}
	public class LifestealResistanceManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <OnBattleStart>d__3 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

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

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

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

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

			private bool MoveNext()
			{
				if (<>1__state != 0)
				{
					return false;
				}
				<>1__state = -1;
				if ((Object)(object)PlayerManager.instance == (Object)null)
				{
					return false;
				}
				foreach (Player player in PlayerManager.instance.players)
				{
					if ((Object)(object)player != (Object)null)
					{
						instance?.RebuildForPlayer(player.playerID);
					}
				}
				return false;
			}

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

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

		public static LifestealResistanceManager instance;

		private readonly Dictionary<int, float> _reductionByPlayer = new Dictionary<int, float>();

		private void Awake()
		{
			instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			GameModeManager.AddHook("BattleStart", (Func<IGameModeHandler, IEnumerator>)OnBattleStart);
			SLog.Section("LifestealResistanceManager — Awake");
		}

		[IteratorStateMachine(typeof(<OnBattleStart>d__3))]
		private static IEnumerator OnBattleStart(IGameModeHandler gm)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <OnBattleStart>d__3(0);
		}

		private void OnDestroy()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		public float GetReduction(int playerID)
		{
			if (!_reductionByPlayer.TryGetValue(playerID, out var value))
			{
				return 0f;
			}
			return value;
		}

		public float GetReductionPercent(int playerID)
		{
			return GetReduction(playerID) * 100f;
		}

		public void RebuildForPlayer(int playerID)
		{
			if (!((Object)(object)PlayerManager.instance == (Object)null))
			{
				Player val = PlayerManager.instance.players.Find((Player p) => p.playerID == playerID);
				if (val?.data?.currentCards != null)
				{
					float num = LifestealHandRebuild.ComputeReductionFromHand(val.data.currentCards);
					_reductionByPlayer[playerID] = num;
					SLog.Line($"LifestealResistance rebuild player={playerID} reduction={num * 100f:F0}%");
				}
			}
		}

		public float ApplyResistance(int playerID, float rawHeal, out float resistedAmount)
		{
			float reduction = GetReduction(playerID);
			resistedAmount = rawHeal * reduction;
			return rawHeal - resistedAmount;
		}
	}
}
namespace ShieldsMod.Cards
{
	public static class CardArtLoader
	{
		private static readonly Dictionary<string, GameObject> Cache = new Dictionary<string, GameObject>();

		public static string AssetsDirectory => Path.Combine(Plugin.PluginDirectory, "assets");

		public static GameObject Load(string fileName)
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Expected O, but got Unknown
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			SLog.Section("CardArtLoader.Load — '" + fileName + "'");
			SLog.Line("AssetsDirectory = " + AssetsDirectory);
			if (string.IsNullOrEmpty(fileName))
			{
				SLog.Warn("Load called with empty fileName — returning null.");
				return null;
			}
			if (Cache.TryGetValue(fileName, out var value) && (Object)(object)value != (Object)null)
			{
				SLog.Line("Returning cached art object.");
				return value;
			}
			string text = Path.Combine(AssetsDirectory, fileName);
			SLog.Line("Full path = " + text);
			SLog.Line($"File.Exists = {File.Exists(text)}");
			if (!File.Exists(text))
			{
				SLog.Warn("Card art not found at: " + text);
				return null;
			}
			byte[] array = File.ReadAllBytes(text);
			SLog.Line($"Read {array.Length} bytes.");
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			bool flag = ImageConversion.LoadImage(val, array);
			SLog.Line($"Texture.LoadImage = {flag}, size = {((Texture)val).width}x{((Texture)val).height}");
			if (!flag)
			{
				SLog.Warn("Failed to decode card art: " + text);
				Object.Destroy((Object)(object)val);
				return null;
			}
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			Sprite sprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
			GameObject val2 = new GameObject("ShieldsCardArt_" + fileName);
			Object.DontDestroyOnLoad((Object)(object)val2);
			RectTransform obj = val2.AddComponent<RectTransform>();
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			obj.offsetMin = Vector2.zero;
			obj.offsetMax = Vector2.zero;
			((Transform)obj).localPosition = Vector3.up * 10000f;
			Image obj2 = val2.AddComponent<Image>();
			obj2.sprite = sprite;
			obj2.preserveAspect = true;
			((Graphic)obj2).raycastTarget = false;
			Cache[fileName] = val2;
			SLog.Line("Loaded card art '" + fileName + "' from " + text);
			return val2;
		}
	}
	internal static class LifestealCardDeltaRegistrar
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<int, float> <>9__1_2;

			public static Func<int, float> <>9__1_3;

			public static Func<IEnumerable<CardInfo>, float> <>9__1_4;

			public static SimpleDeltaProvider <>9__1_1;

			internal float <RegisterTier>b__1_2(int id)
			{
				return LifestealResistanceManager.instance.GetReductionPercent(id);
			}

			internal IReadOnlyList<(string label, string before, string after)> <RegisterTier>b__1_1(Player player, CardInfo cardInfo)
			{
				return ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Lifesteal Resistance", (int id) => LifestealResistanceManager.instance.GetReductionPercent(id), (IEnumerable<CardInfo> cards) => LifestealHandRebuild.ComputeReductionFromHand(cards));
			}

			internal float <RegisterTier>b__1_3(int id)
			{
				return LifestealResistanceManager.instance.GetReductionPercent(id);
			}

			internal float <RegisterTier>b__1_4(IEnumerable<CardInfo> cards)
			{
				return LifestealHandRebuild.ComputeReductionFromHand(cards);
			}
		}

		internal static void RegisterAll()
		{
			SLog.Section("LifestealCardDeltaRegistrar — RegisterAll");
			RegisterTier(LifestealCardRegistry.Lv1, 1);
			RegisterTier(LifestealCardRegistry.Lv2, 2);
			RegisterTier(LifestealCardRegistry.Lv3, 3);
		}

		private static void RegisterTier(CardInfo card, int level)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			if ((Object)(object)card == (Object)null)
			{
				return;
			}
			LifestealHandRebuild.RegisterTier(card.cardName, level);
			CardDeltaRegistry.RegisterSimple(card.cardName, (SimpleDeltaProvider)((Player player, CardInfo _) => ResistanceDeltaHelper.ComputeAddDelta(player, level, "Lifesteal Resistance", (int id) => LifestealResistanceManager.instance.GetReductionPercent(id))));
			string cardName = card.cardName;
			object obj = <>c.<>9__1_1;
			if (obj == null)
			{
				SimpleDeltaProvider val = (Player player, CardInfo cardInfo) => ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Lifesteal Resistance", (int id) => LifestealResistanceManager.instance.GetReductionPercent(id), (IEnumerable<CardInfo> cards) => LifestealHandRebuild.ComputeReductionFromHand(cards));
				<>c.<>9__1_1 = val;
				obj = (object)val;
			}
			CardDeltaRegistry.RegisterRemovalSimple(cardName, (SimpleDeltaProvider)obj);
			SLog.Line($"Registered lifesteal delta preview for '{card.cardName}' (LV{level}).");
		}
	}
	internal static class LifestealCardRegistrar
	{
		internal static void RegisterAll()
		{
			SLog.Section("LifestealCardRegistrar — RegisterAll");
			CustomCard.BuildCard<LifestealResistanceLv3>((Action<CardInfo>)delegate(CardInfo ci)
			{
				LifestealCardRegistry.Lv3 = ci;
			});
			CustomCard.BuildCard<LifestealResistanceLv2>((Action<CardInfo>)delegate(CardInfo ci)
			{
				LifestealCardRegistry.Lv2 = ci;
			});
			CustomCard.BuildCard<LifestealResistanceLv1>((Action<CardInfo>)OnLv1Built);
		}

		private static void OnLv1Built(CardInfo ci)
		{
			LifestealCardRegistry.Lv1 = ci;
			SLog.Line("Registered Lifesteal Resistance LV1: " + ci.cardName);
			LifestealCardDeltaRegistrar.RegisterAll();
		}
	}
	internal static class LifestealCardRegistry
	{
		internal static CardInfo Lv1;

		internal static CardInfo Lv2;

		internal static CardInfo Lv3;
	}
	public abstract class LifestealResistanceBase : CustomCard
	{
		protected abstract int Level { get; }

		protected abstract string ArtFileName { get; }

		protected abstract Rarity CardRarity { get; }

		protected override string GetTitle()
		{
			return "Lifesteal Resistance " + Roman(Level);
		}

		protected override string GetDescription()
		{
			return ResistanceCardText.Description(Level, "lifesteal");
		}

		protected override CardInfoStat[] GetStats()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0038: Expected O, but got Unknown
			return (CardInfoStat[])(object)new CardInfoStat[1]
			{
				new CardInfoStat
				{
					positive = true,
					amount = ResistanceCardText.StatAmount(Level),
					stat = "Life Steal Resist",
					simepleAmount = (SimpleAmount)0
				}
			};
		}

		protected override Rarity GetRarity()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return CardRarity;
		}

		protected override GameObject GetCardArt()
		{
			return CardArtLoader.Load(ArtFileName);
		}

		protected override CardThemeColorType GetTheme()
		{
			return (CardThemeColorType)4;
		}

		public override string GetModName()
		{
			return "ShieldsMod";
		}

		public override void SetupCard(CardInfo cardInfo, Gun gun, ApplyCardStats cardStats, CharacterStatModifiers statModifiers, Block block)
		{
			cardInfo.allowMultiple = false;
		}

		public override void OnAddCard(Player player, Gun gun, GunAmmo gunAmmo, CharacterData data, HealthHandler health, Gravity gravity, Block block, CharacterStatModifiers characterStats)
		{
			if (!((Object)(object)player == (Object)null))
			{
				string cardName = (((Object)(object)base.cardInfo != (Object)null) ? base.cardInfo.cardName : null);
				ResistanceCardOnAdd.Apply(player, data, Level, cardName, (IEnumerable<CardInfo> cards) => LifestealHandRebuild.ComputeReductionFromHand(cards), delegate(int id)
				{
					LifestealResistanceManager.instance?.RebuildForPlayer(id);
				});
				SLog.Section($"LifestealResistance LV{Level} — OnAddCard");
				SLog.Line($"player={player.playerID} reduction={LifestealResistanceManager.instance?.GetReductionPercent(player.playerID):F0}%");
			}
		}

		private static string Roman(int level)
		{
			return level switch
			{
				1 => "I", 
				2 => "II", 
				3 => "III", 
				_ => level.ToString(), 
			};
		}
	}
	public class LifestealResistanceLv1 : LifestealResistanceBase
	{
		protected override int Level => 1;

		protected override string ArtFileName => "lifesteal_resistance_lv1.png";

		protected override Rarity CardRarity => (Rarity)1;
	}
	public class LifestealResistanceLv2 : LifestealResistanceBase
	{
		protected override int Level => 2;

		protected override string ArtFileName => "lifesteal_resistance_lv2.png";

		protected override Rarity CardRarity => (Rarity)2;
	}
	public class LifestealResistanceLv3 : LifestealResistanceBase
	{
		protected override int Level => 3;

		protected override string ArtFileName => "lifesteal_resistance_lv3.png";

		protected override Rarity CardRarity => RarityHelper.Epic;
	}
	internal static class PoisonCardDeltaRegistrar
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<int, float> <>9__1_2;

			public static Func<int, float> <>9__1_3;

			public static Func<IEnumerable<CardInfo>, float> <>9__1_4;

			public static SimpleDeltaProvider <>9__1_1;

			internal float <RegisterTier>b__1_2(int id)
			{
				return PoisonResistanceManager.instance.GetReductionPercent(id);
			}

			internal IReadOnlyList<(string label, string before, string after)> <RegisterTier>b__1_1(Player player, CardInfo cardInfo)
			{
				return ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Poison Resistance", (int id) => PoisonResistanceManager.instance.GetReductionPercent(id), (IEnumerable<CardInfo> cards) => PoisonHandRebuild.ComputeReductionFromHand(cards));
			}

			internal float <RegisterTier>b__1_3(int id)
			{
				return PoisonResistanceManager.instance.GetReductionPercent(id);
			}

			internal float <RegisterTier>b__1_4(IEnumerable<CardInfo> cards)
			{
				return PoisonHandRebuild.ComputeReductionFromHand(cards);
			}
		}

		internal static void RegisterAll()
		{
			SLog.Section("PoisonCardDeltaRegistrar — RegisterAll");
			RegisterTier(PoisonCardRegistry.Lv1, 1);
			RegisterTier(PoisonCardRegistry.Lv2, 2);
			RegisterTier(PoisonCardRegistry.Lv3, 3);
		}

		private static void RegisterTier(CardInfo card, int level)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			if ((Object)(object)card == (Object)null)
			{
				return;
			}
			PoisonHandRebuild.RegisterTier(card.cardName, level);
			CardDeltaRegistry.RegisterSimple(card.cardName, (SimpleDeltaProvider)((Player player, CardInfo _) => ResistanceDeltaHelper.ComputeAddDelta(player, level, "Poison Resistance", (int id) => PoisonResistanceManager.instance.GetReductionPercent(id))));
			string cardName = card.cardName;
			object obj = <>c.<>9__1_1;
			if (obj == null)
			{
				SimpleDeltaProvider val = (Player player, CardInfo cardInfo) => ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Poison Resistance", (int id) => PoisonResistanceManager.instance.GetReductionPercent(id), (IEnumerable<CardInfo> cards) => PoisonHandRebuild.ComputeReductionFromHand(cards));
				<>c.<>9__1_1 = val;
				obj = (object)val;
			}
			CardDeltaRegistry.RegisterRemovalSimple(cardName, (SimpleDeltaProvider)obj);
			SLog.Line($"Registered poison delta preview for '{card.cardName}' (LV{level}).");
		}
	}
	internal static class PoisonCardRegistrar
	{
		internal static void RegisterAll()
		{
			SLog.Section("PoisonCardRegistrar — RegisterAll");
			CustomCard.BuildCard<PoisonResistanceLv3>((Action<CardInfo>)delegate(CardInfo ci)
			{
				PoisonCardRegistry.Lv3 = ci;
			});
			CustomCard.BuildCard<PoisonResistanceLv2>((Action<CardInfo>)delegate(CardInfo ci)
			{
				PoisonCardRegistry.Lv2 = ci;
			});
			CustomCard.BuildCard<PoisonResistanceLv1>((Action<CardInfo>)OnLv1Built);
		}

		private static void OnLv1Built(CardInfo ci)
		{
			PoisonCardRegistry.Lv1 = ci;
			SLog.Line("Registered Poison Resistance LV1: " + ci.cardName);
			PoisonCardDeltaRegistrar.RegisterAll();
		}
	}
	internal static class PoisonCardRegistry
	{
		internal static CardInfo Lv1;

		internal static CardInfo Lv2;

		internal static CardInfo Lv3;
	}
	public abstract class PoisonResistanceBase : CustomCard
	{
		protected abstract int Level { get; }

		protected abstract string ArtFileName { get; }

		protected abstract Rarity CardRarity { get; }

		protected override string GetTitle()
		{
			return "Poison Resistance " + Roman(Level);
		}

		protected override string GetDescription()
		{
			return ResistanceCardText.Description(Level, "poison");
		}

		protected override CardInfoStat[] GetStats()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0038: Expected O, but got Unknown
			return (CardInfoStat[])(object)new CardInfoStat[1]
			{
				new CardInfoStat
				{
					positive = true,
					amount = ResistanceCardText.StatAmount(Level),
					stat = "Poison Resist",
					simepleAmount = (SimpleAmount)0
				}
			};
		}

		protected override Rarity GetRarity()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return CardRarity;
		}

		protected override GameObject GetCardArt()
		{
			return CardArtLoader.Load(ArtFileName);
		}

		protected override CardThemeColorType GetTheme()
		{
			return (CardThemeColorType)5;
		}

		public override string GetModName()
		{
			return "ShieldsMod";
		}

		public override void SetupCard(CardInfo cardInfo, Gun gun, ApplyCardStats cardStats, CharacterStatModifiers statModifiers, Block block)
		{
			cardInfo.allowMultiple = false;
		}

		public override void OnAddCard(Player player, Gun gun, GunAmmo gunAmmo, CharacterData data, HealthHandler health, Gravity gravity, Block block, CharacterStatModifiers characterStats)
		{
			if (!((Object)(object)player == (Object)null))
			{
				string cardName = (((Object)(object)base.cardInfo != (Object)null) ? base.cardInfo.cardName : null);
				ResistanceCardOnAdd.Apply(player, data, Level, cardName, (IEnumerable<CardInfo> cards) => PoisonHandRebuild.ComputeReductionFromHand(cards), delegate(int id)
				{
					PoisonResistanceManager.instance?.RebuildForPlayer(id);
				});
				SLog.Section($"PoisonResistance LV{Level} — OnAddCard");
				SLog.Line($"player={player.playerID} reduction={PoisonResistanceManager.instance?.GetReductionPercent(player.playerID):F0}%");
			}
		}

		private static string Roman(int level)
		{
			return level switch
			{
				1 => "I", 
				2 => "II", 
				3 => "III", 
				_ => level.ToString(), 
			};
		}
	}
	public class PoisonResistanceLv1 : PoisonResistanceBase
	{
		protected override int Level => 1;

		protected override string ArtFileName => "poison_resistance_lv1.png";

		protected override Rarity CardRarity => (Rarity)1;
	}
	public class PoisonResistanceLv2 : PoisonResistanceBase
	{
		protected override int Level => 2;

		protected override string ArtFileName => "poison_resistance_lv2.png";

		protected override Rarity CardRarity => (Rarity)2;
	}
	public class PoisonResistanceLv3 : PoisonResistanceBase
	{
		protected override int Level => 3;

		protected override string ArtFileName => "poison_resistance_lv3.png";

		protected override Rarity CardRarity => RarityHelper.Epic;
	}
	internal static class RarityHelper
	{
		public static Rarity Scarce => RarityUtils.GetRarity("Scarce");

		public static Rarity Epic => RarityUtils.GetRarity("Epic");

		public static Rarity Legendary => RarityUtils.GetRarity("Legendary");
	}
	internal static class ResistanceCardOnAdd
	{
		internal static void Apply(Player player, CharacterData data, int level, string cardName, Func<IEnumerable<CardInfo>, float> computeFromHand, Action<int> rebuild)
		{
			if (!((Object)(object)player == (Object)null) && computeFromHand != null)
			{
				IEnumerable<CardInfo> arg = player.data?.currentCards?.Where((CardInfo c) => (Object)(object)c != (Object)null && c.cardName != cardName) ?? Enumerable.Empty<CardInfo>();
				ResistanceTierLogic.ApplyCard(computeFromHand(arg), level, out var healthMultiplier);
				if (healthMultiplier.HasValue)
				{
					ResistanceTierLogic.ApplyHealthBonus(data, healthMultiplier.Value);
				}
				rebuild?.Invoke(player.playerID);
			}
		}
	}
	internal static class ResistanceCardText
	{
		internal static string Description(int level, string effectLabel)
		{
			return level switch
			{
				1 => "Sets " + effectLabel + " resistance to 25%, or +5% if you already have resistance.", 
				2 => "Sets " + effectLabel + " resistance to 50% if below 50%; otherwise +5% resistance and +10% max HP.", 
				3 => "Sets " + effectLabel + " resistance to 75% if below 75%; otherwise +5% resistance and +25% max HP.", 
				_ => "Improves " + effectLabel + " resistance.", 
			};
		}

		internal static string StatAmount(int level)
		{
			return level switch
			{
				1 => "25% / +5%", 
				2 => "50% / +5%", 
				3 => "75% / +5%", 
				_ => "—", 
			};
		}
	}
	internal static class ResistanceDeltaHelper
	{
		internal static IReadOnlyList<(string label, string before, string after)> ComputeAddDelta(Player player, int level, string statLabel, Func<int, float> getReductionPercent)
		{
			if ((Object)(object)player == (Object)null || getReductionPercent == null)
			{
				return Array.Empty<(string, string, string)>();
			}
			float num = getReductionPercent(player.playerID);
			float? healthMultiplier;
			float num2 = ResistanceTierLogic.ApplyCard(num / 100f, level, out healthMultiplier) * 100f;
			List<(string, string, string)> list = new List<(string, string, string)> { (statLabel, $"{num:F0}%", $"{num2:F0}%") };
			if (healthMultiplier.HasValue && (Object)(object)player.data != (Object)null)
			{
				float maxHealth = player.data.maxHealth;
				float num3 = maxHealth * healthMultiplier.Value;
				list.Add(("HP", $"{maxHealth:F0}", $"{num3:F0}"));
			}
			return list;
		}

		internal static IReadOnlyList<(string label, string before, string after)> ComputeRemovalDelta(Player player, CardInfo cardToRemove, string statLabel, Func<int, float> getReductionPercent, Func<IEnumerable<CardInfo>, float> computeFromHand)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)cardToRemove == (Object)null || getReductionPercent == null || computeFromHand == null)
			{
				return Array.Empty<(string, string, string)>();
			}
			float num = getReductionPercent(player.playerID);
			IEnumerable<CardInfo> arg = player.data?.currentCards?.Where((CardInfo c) => (Object)(object)c != (Object)null && ((Object)c).name != ((Object)cardToRemove).name) ?? Enumerable.Empty<CardInfo>();
			float num2 = computeFromHand(arg) * 100f;
			if (Mathf.Approximately(num, num2))
			{
				return Array.Empty<(string, string, string)>();
			}
			return new(string, string, string)[1] { (statLabel, $"{num:F0}%", $"{num2:F0}%") };
		}
	}
	internal static class RtgPrerequisiteBridge
	{
		private static MethodInfo _registerMethod;

		private static bool _resolved;

		public static bool IsAvailable
		{
			get
			{
				Resolve();
				return _registerMethod != null;
			}
		}

		private static void Resolve()
		{
			if (_resolved)
			{
				return;
			}
			_resolved = true;
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "DeckBuilder");
				if (assembly == null)
				{
					SLog.Warn("DeckBuilder assembly not found — shield unlock chain will not be registered.");
					return;
				}
				Type type = assembly.GetType("DeckBuilder.CardPrerequisiteRegistry");
				if (type == null)
				{
					SLog.Warn("DeckBuilder CardPrerequisiteRegistry type not found.");
					return;
				}
				_registerMethod = type.GetMethod("RegisterPrerequisite", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(string),
					typeof(string)
				}, null);
				if (_registerMethod == null)
				{
					SLog.Warn("RegisterPrerequisite(string, string) not found on CardPrerequisiteRegistry.");
				}
			}
			catch (Exception ex)
			{
				SLog.Error("Failed to resolve DeckBuilder registry: " + ex.Message);
			}
		}

		internal static bool Register(string cardName, string requiredCardName)
		{
			Resolve();
			if (_registerMethod == null)
			{
				return false;
			}
			try
			{
				_registerMethod.Invoke(null, new object[2] { cardName, requiredCardName });
				return true;
			}
			catch (Exception ex)
			{
				SLog.Error("RegisterPrerequisite invoke failed: " + ex.Message);
				return false;
			}
		}
	}
	internal static class ShieldCardDeltaRegistrar
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static SimpleDeltaProvider <>9__1_1;

			internal IReadOnlyList<(string label, string before, string after)> <RegisterTier>b__1_1(Player player, CardInfo cardInfo)
			{
				return ComputeShieldRemoval(player, cardInfo);
			}
		}

		internal static void RegisterAll()
		{
			SLog.Section("ShieldCardDeltaRegistrar — RegisterAll");
			RegisterTier(ShieldCardRegistry.Lv1, 100f, 1.2f);
			RegisterTier(ShieldCardRegistry.Lv2, 150f, 1.5f);
			RegisterTier(ShieldCardRegistry.Lv3, 250f, 2f);
			RegisterTier(ShieldCardRegistry.Lv4, 500f, 3f);
			RegisterTier(ShieldCardRegistry.Lv5, 1000f, 3.5f);
		}

		private static void RegisterTier(CardInfo card, float firstShieldMax, float stackMultiplier)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			if ((Object)(object)card == (Object)null)
			{
				SLog.Warn("ShieldCardDeltaRegistrar — skipped null card reference.");
				return;
			}
			ShieldHandRebuild.RegisterTier(card, firstShieldMax, stackMultiplier);
			CardDeltaRegistry.RegisterSimple(card.cardName, (SimpleDeltaProvider)((Player player, CardInfo _) => ComputeShieldDelta(player, firstShieldMax, stackMultiplier)));
			string cardName = card.cardName;
			object obj = <>c.<>9__1_1;
			if (obj == null)
			{
				SimpleDeltaProvider val = (Player player, CardInfo cardInfo) => ComputeShieldRemoval(player, cardInfo);
				<>c.<>9__1_1 = val;
				obj = (object)val;
			}
			CardDeltaRegistry.RegisterRemovalSimple(cardName, (SimpleDeltaProvider)obj);
			SLog.Line($"Registered stat-delta preview for '{card.cardName}' (first={firstShieldMax:F0}, x{stackMultiplier:F2}).");
		}

		private static IReadOnlyList<(string label, string before, string after)> ComputeShieldDelta(Player player, float firstShieldMax, float stackMultiplier)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)ShieldManager.instance == (Object)null)
			{
				return Array.Empty<(string, string, string)>();
			}
			ShieldState shield = ShieldManager.instance.GetShield(player.playerID);
			float max = shield.Max;
			float num = (shield.HasShield ? (max * stackMultiplier) : firstShieldMax);
			return new(string, string, string)[1] { ("Shield Max", $"{max:F0}", $"{num:F0}") };
		}

		private static IReadOnlyList<(string label, string before, string after)> ComputeShieldRemoval(Player player, CardInfo cardToRemove)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)ShieldManager.instance == (Object)null || (Object)(object)cardToRemove == (Object)null)
			{
				return Array.Empty<(string, string, string)>();
			}
			float max = ShieldManager.instance.GetShield(player.playerID).Max;
			float num = ShieldHandRebuild.ComputeMaxFromHandExcluding(player.data?.currentCards, cardToRemove);
			if (Mathf.Approximately(max, num))
			{
				return Array.Empty<(string, string, string)>();
			}
			string item = ((num > 0f) ? $"{num:F0}" : "None");
			return new(string, string, string)[1] { ("Shield Health", $"{max:F0}", item) };
		}
	}
	internal static class ShieldCardRegistrar
	{
		internal static void RegisterAll()
		{
			SLog.Section("ShieldCardRegistrar — RegisterAll");
			CustomCard.BuildCard<UpgradeShieldLv5>((Action<CardInfo>)delegate(CardInfo ci)
			{
				ShieldCardRegistry.Lv5 = ci;
			});
			CustomCard.BuildCard<UpgradeShieldLv4>((Action<CardInfo>)delegate(CardInfo ci)
			{
				ShieldCardRegistry.Lv4 = ci;
			});
			CustomCard.BuildCard<UpgradeShieldLv3>((Action<CardInfo>)delegate(CardInfo ci)
			{
				ShieldCardRegistry.Lv3 = ci;
			});
			CustomCard.BuildCard<UpgradeShieldLv2>((Action<CardInfo>)delegate(CardInfo ci)
			{
				ShieldCardRegistry.Lv2 = ci;
			});
			CustomCard.BuildCard<UpgradeShieldLv1>((Action<CardInfo>)OnLv1Built);
		}

		private static void OnLv1Built(CardInfo ci)
		{
			ShieldCardRegistry.Lv1 = ci;
			SLog.Line("Registered LV1: " + ci.cardName);
			ShieldCardDeltaRegistrar.RegisterAll();
		}
	}
	internal static class ShieldCardRegistry
	{
		internal static CardInfo Lv1;

		internal static CardInfo Lv2;

		internal static CardInfo Lv3;

		internal static CardInfo Lv4;

		internal static CardInfo Lv5;
	}
	internal static class StunCardDeltaRegistrar
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<int, float> <>9__1_2;

			public static Func<int, float> <>9__1_3;

			public static Func<IEnumerable<CardInfo>, float> <>9__1_4;

			public static SimpleDeltaProvider <>9__1_1;

			internal float <RegisterTier>b__1_2(int id)
			{
				return StunResistanceManager.instance.GetReductionPercent(id);
			}

			internal IReadOnlyList<(string label, string before, string after)> <RegisterTier>b__1_1(Player player, CardInfo cardInfo)
			{
				return ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Stun Resistance", (int id) => StunResistanceManager.instance.GetReductionPercent(id), (IEnumerable<CardInfo> cards) => StunHandRebuild.ComputeReductionFromHand(cards));
			}

			internal float <RegisterTier>b__1_3(int id)
			{
				return StunResistanceManager.instance.GetReductionPercent(id);
			}

			internal float <RegisterTier>b__1_4(IEnumerable<CardInfo> cards)
			{
				return StunHandRebuild.ComputeReductionFromHand(cards);
			}
		}

		internal static void RegisterAll()
		{
			SLog.Section("StunCardDeltaRegistrar — RegisterAll");
			RegisterTier(StunCardRegistry.Lv1, 1);
			RegisterTier(StunCardRegistry.Lv2, 2);
			RegisterTier(StunCardRegistry.Lv3, 3);
		}

		private static void RegisterTier(CardInfo card, int level)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			if ((Object)(object)card == (Object)null)
			{
				return;
			}
			StunHandRebuild.RegisterTier(card.cardName, level);
			CardDeltaRegistry.RegisterSimple(card.cardName, (SimpleDeltaProvider)((Player player, CardInfo _) => ResistanceDeltaHelper.ComputeAddDelta(player, level, "Stun Resistance", (int id) => StunResistanceManager.instance.GetReductionPercent(id))));
			string cardName = card.cardName;
			object obj = <>c.<>9__1_1;
			if (obj == null)
			{
				SimpleDeltaProvider val = (Player player, CardInfo cardInfo) => ResistanceDeltaHelper.ComputeRemovalDelta(player, cardInfo, "Stun Resistance", (int id) => StunResistanceManager.instance.GetReductionPercent(id), (IEnumerable<CardInfo> cards) => StunHandRebuild.ComputeReductionFromHand(cards));
				<>c.<>9__1_1 = val;
				obj = (object)val;
			}
			CardDeltaRegistry.RegisterRemovalSimple(cardName, (SimpleDeltaProvider)obj);
			SLog.Line($"Registered stun delta preview for '{card.cardName}' (LV{level}).");
		}
	}
	internal static class StunCardRegistrar
	{
		internal static void RegisterAll()
		{
			SLog.Section("StunCardRegistrar — RegisterAll");
			CustomCard.BuildCard<StunResistanceLv3>((Action<CardInfo>)delegate(CardInfo ci)
			{
				StunCardRegistry.Lv3 = ci;
			});
			CustomCard.BuildCard<StunResistanceLv2>((Action<CardInfo>)delegate(CardInfo ci)
			{
				StunCardRegistry.Lv2 = ci;
			});
			CustomCard.BuildCard<StunResistanceLv1>((Action<CardInfo>)OnLv1Built);
		}

		private static void OnLv1Built(CardInfo ci)
		{
			StunCardRegistry.Lv1 = ci;
			SLog.Line("Registered Stun Resistance LV1: " + ci.cardName);
			StunCardDeltaRegistrar.RegisterAll();
		}
	}
	internal static class StunCardRegistry
	{
		internal static CardInfo Lv1;

		internal static CardInfo Lv2;

		internal static CardInfo Lv3;
	}
	public abstract class StunResistanceBase : CustomCard
	{
		protected abstract int Level { get; }

		protected abstract string ArtFileName { get; }

		protected abstract Rarity CardRarity { get; }

		protected override string GetTitle()
		{
			return "Stun Resistance " + Roman(Level);
		}

		protected override string GetDescription()
		{
			return ResistanceCardText.Description(Level, "stun");
		}

		protected override CardInfoStat[] GetStats()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0038: Expected O, but got Unknown
			return (CardInfoStat[])(object)new CardInfoStat[1]
			{
				new CardInfoStat
				{
					positive = true,
					amount = ResistanceCardText.StatAmount(Level),
					stat = "Stun Resist",
					simepleAmount = (SimpleAmount)0
				}
			};
		}

		protected override Rarity GetRarity()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return CardRarity;
		}

		protected override GameObject GetCardArt()
		{
			return CardArtLoader.Load(ArtFileName);
		}

		protected override CardThemeColorType GetTheme()
		{
			return (CardThemeColorType)7;
		}

		public override string GetModName()
		{
			return "ShieldsMod";
		}

		public override void SetupCard(CardInfo cardInfo, Gun gun, ApplyCardStats cardStats, CharacterStatModifiers statModifiers, Block block)
		{
			cardInfo.allowMultiple = false;
		}

		public override void OnAddCard(Player player, Gun gun, GunAmmo gunAmmo, CharacterData data, HealthHandler health, Gravity gravity, Block block, CharacterStatModifiers characterStats)
		{
			if (!((Object)(object)player == (Object)null))
			{
				string cardName = (((Object)(object)base.cardInfo != (Object)null) ? base.cardInfo.cardName : null);
				ResistanceCardOnAdd.Apply(player, data, Level, cardName, (IEnumerable<CardInfo> cards) => StunHandRebuild.ComputeReductionFromHand(cards), delegate(int id)
				{
					StunResistanceManager.instance?.RebuildForPlayer(id);
				});
				SLog.Section($"StunResistance LV{Level} — OnAddCard");
				SLog.Line($"player={player.playerID} reduction={StunResistanceManager.instance?.GetReductionPercent(player.playerID):F0}%");
			}
		}

		private static string Roman(int level)
		{
			return level switch
			{
				1 => "I", 
				2 => "II", 
				3 => "III", 
				_ => level.ToString(), 
			};
		}
	}
	public class StunResistanceLv1 : StunResistanceBase
	{
		protected override int Level => 1;

		protected override string ArtFileName => "stun_resistance_lv1.png";

		protected override Rarity CardRarity => (Rarity)1;
	}
	public class StunResistanceLv2 : StunResistanceBase
	{
		protected override int Level => 2;

		protected override string ArtFileName => "stun_resistance_lv2.png";

		protected override Rarity CardRarity => (Rarity)2;
	}
	public class StunResistanceLv3 : StunResistanceBase
	{
		protected override int Level => 3;

		protected override string ArtFileName => "stun_resistance_lv3.png";

		protected override Rarity CardRarity => RarityHelper.Epic;
	}
	public abstract class UpgradeShieldHealthBase : CustomCard
	{
		protected abstract int Level { get; }

		protected abstract float FirstShieldMax { get; }

		protected abstract float Multiplier { get; }

		protected abstract string ArtFileName { get; }

		protected abstract Rarity CardRarity { get; }

		protected override string GetTitle()
		{
			return "Upgrade Shield Health " + Roman(Level);
		}

		protected override string GetDescription()
		{
			return "Grants or increases max shield health by " + PercentLabel(Multiplier) + ". First pickup sets a base shield if you have none.";
		}

		protected override CardInfoStat[] GetStats()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0038: Expected O, but got Unknown
			return (CardInfoStat[])(object)new CardInfoStat[1]
			{
				new CardInfoStat
				{
					positive = true,
					amount = PercentLabel(Multiplier),
					stat = "Shield Max",
					simepleAmount = (SimpleAmount)0
				}
			};
		}

		protected override Rarity GetRarity()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return CardRarity;
		}

		protected override GameObject GetCardArt()
		{
			return CardArtLoader.Load(ArtFileName);
		}

		protected override CardThemeColorType GetTheme()
		{
			return (CardThemeColorType)2;
		}

		public override string GetModName()
		{
			return "ShieldsMod";
		}

		public override void SetupCard(CardInfo cardInfo, Gun gun, ApplyCardStats cardStats, CharacterStatModifiers statModifiers, Block block)
		{
			cardInfo.allowMultiple = false;
		}

		public override void OnAddCard(Player player, Gun gun, GunAmmo gunAmmo, CharacterData data, HealthHandler health, Gravity gravity, Block block, CharacterStatModifiers characterStats)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)ShieldManager.instance == (Object)null))
			{
				int playerID = player.playerID;
				ShieldState orCreateShield = ShieldManager.instance.GetOrCreateShield(playerID);
				float max = orCreateShield.Max;
				if (!orCreateShield.HasShield)
				{
					orCreateShield.Max = FirstShieldMax;
					orCreateShield.Current = orCreateShield.Max;
				}
				else
				{
					orCreateShield.Max *= Multiplier;
					orCreateShield.Current = Mathf.Min(orCreateShield.Current, orCreateShield.Max);
				}
				ShieldManager.instance.RefreshVisual(playerID);
				SLog.Section($"UpgradeShieldHealth LV{Level} — OnAddCard");
				SLog.Line($"player={playerID} firstMax={FirstShieldMax:F0} multiplier={Multiplier:F2} max {max:F1} -> {orCreateShield.Max:F1}");
			}
		}

		private static string PercentLabel(float multiplier)
		{
			return $"+{Mathf.RoundToInt((multiplier - 1f) * 100f)}%";
		}

		private static string Roman(int level)
		{
			return level switch
			{
				1 => "I", 
				2 => "II", 
				3 => "III", 
				4 => "IV", 
				5 => "V", 
				_ => level.ToString(), 
			};
		}
	}
	public class UpgradeShieldLv1 : UpgradeShieldHealthBase
	{
		protected override int Level => 1;

		protected override float FirstShieldMax => 100f;

		protected override float Multiplier => 1.2f;

		protected override string ArtFileName => "lv1_artwork.png";

		protected override Rarity CardRarity => (Rarity)0;
	}
	public class UpgradeShieldLv2 : UpgradeShieldHealthBase
	{
		protected override int Level => 2;

		protected override float FirstShieldMax => 150f;

		protected override float Multiplier => 1.5f;

		protected override string ArtFileName => "lv2_artwork.png";

		protected override Rarity CardRarity => RarityHelper.Scarce;
	}
	public class UpgradeShieldLv3 : UpgradeShieldHealthBase
	{
		protected override int Level => 3;

		protected override float FirstShieldMax => 250f;

		protected override float Multiplier => 2f;

		protected override string ArtFileName => "lv3_artwork.png";

		protected override Rarity CardRarity => (Rarity)1;
	}
	public class UpgradeShieldLv4 : UpgradeShieldHealthBase
	{
		protected override int Level => 4;

		protected override float FirstShieldMax => 500f;

		protected override float Multiplier => 3f;

		protected override string ArtFileName => "lv4_artwork.png";

		protected override Rarity CardRarity => RarityHelper.Epic;
	}
	public class UpgradeShieldLv5 : UpgradeShieldHealthBase
	{
		protected override int Level => 5;

		protected override float FirstShieldMax => 1000f;

		protected override float Multiplier => 3.5f;

		protected override string ArtFileName => "lv5_artwork.png";

		protected override Rarity CardRarity => RarityHelper.Legendary;
	}
}