Decompiled source of MulliganMadness v0.4.9

MulliganMadness.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CardChoiceSpawnUniqueCardPatch.CustomCategories;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ModdingUtils.Extensions;
using ModdingUtils.Utils;
using MulliganMadness.Cards;
using MulliganMadness.Curses;
using MulliganMadness.Patches;
using MulliganMadness.Stats;
using MulliganMadness.UI;
using MulliganMadness.Utils;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnboundLib;
using UnboundLib.Cards;
using UnboundLib.GameModes;
using UnboundLib.Networking;
using UnboundLib.Utils.UI;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using WillsWackyManagers.UnityTools;
using WillsWackyManagers.Utils;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MulliganMadness")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.4.9+55a591fc121163598b5481c37f4191e629e67bfc")]
[assembly: AssemblyProduct("MulliganMadness")]
[assembly: AssemblyTitle("MulliganMadness")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MulliganMadness
{
	[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.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.bukey.rounds.mulliganmadness", "Mulligan Madness", "0.4.9")]
	[BepInProcess("Rounds.exe")]
	public class Plugin : BaseUnityPlugin
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__12_0;

			internal void <Start>b__12_0()
			{
			}
		}

		public const string ModId = "com.bukey.rounds.mulliganmadness";

		public const string ModName = "Mulligan Madness";

		public const string Version = "0.4.9";

		public const string ModInitials = "MM";

		public const string CurseInitials = "MMC";

		public const string CardsMenuName = "MulliganMadness";

		internal static Configs Configs;

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			Instance = this;
			Configs = new Configs(((BaseUnityPlugin)this).Config);
			SessionSettings.InitializeFromConfig();
			SessionSettingsSync.Register();
			SessionRulesBanner.RegisterHooks();
			RoundWinTracker.RegisterHooks();
			try
			{
				Harmony val = new Harmony("com.bukey.rounds.mulliganmadness");
				Type[] types;
				try
				{
					types = typeof(Plugin).Assembly.GetTypes();
				}
				catch (ReflectionTypeLoadException ex)
				{
					types = ex.Types;
					ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
					Exception?[] loaderExceptions = ex.LoaderExceptions;
					logger.LogWarning((object)$"Harmony GetTypes partial load: {((loaderExceptions != null) ? loaderExceptions.Length : 0)} loader error(s)");
				}
				Type[] array = types;
				foreach (Type type in array)
				{
					if (!(type == null))
					{
						try
						{
							val.CreateClassProcessor(type).Patch();
						}
						catch (Exception ex2)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("Harmony skip " + type.FullName + ": " + ex2.GetType().Name + ": " + ex2.Message));
						}
					}
				}
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Harmony patching failed: {arg}");
			}
		}

		private void Start()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			AutoPickCurse.RegisterAll();
			CardRegistration.RegisterAll();
			CardArtFactory.BindLoadedCardInfos();
			NestEggManager.RegisterHooks();
			MmStatus.Register();
			object obj = <>c.<>9__12_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
				};
				<>c.<>9__12_0 = val;
				obj = (object)val;
			}
			Unbound.RegisterMenu("Mulligan Madness", (UnityAction)obj, (Action<GameObject>)DrawSettingsMenu, (GameObject)null, true);
			Unbound.RegisterHandshake("com.bukey.rounds.mulliganmadness", (Action)OnHandshake);
			GameModeManager.AddHook("GameStart", (Func<IGameModeHandler, IEnumerator>)OnGameStart);
			GameModeManager.AddHook("PlayerPickStart", (Func<IGameModeHandler, IEnumerator>)OnPlayerPickStart);
			GameModeManager.AddHook("PlayerPickEnd", (Func<IGameModeHandler, IEnumerator>)OnPlayerPickEnd);
			GameModeManager.AddHook("PickEnd", (Func<IGameModeHandler, IEnumerator>)OnPickEnd);
			ExtensionMethods.GetOrAddComponent<TakeAllButton>(((Component)this).gameObject, false);
			ExtensionMethods.GetOrAddComponent<AutoPickController>(((Component)this).gameObject, false);
			ExtensionMethods.GetOrAddComponent<SessionVoteTicker>(((Component)this).gameObject, false);
			ExtensionMethods.GetOrAddComponent<FumbleController>(((Component)this).gameObject, false);
			ExtensionMethods.GetOrAddComponent<BlindDraftController>(((Component)this).gameObject, false);
			ExtensionMethods.ExecuteAfterSeconds((MonoBehaviour)(object)Instance, 0.5f, (Action)CardArtFactory.BindLoadedCardInfos);
			ExtensionMethods.ExecuteAfterSeconds((MonoBehaviour)(object)Instance, 2.5f, (Action)CardArtFactory.BindLoadedCardInfos);
		}

		private static void OnHandshake()
		{
			if (SessionSettings.IsHost && !PhotonNetwork.OfflineMode && PhotonNetwork.InRoom)
			{
				SessionSettingsSync.BroadcastToAllIfHost();
			}
		}

		private static IEnumerator OnGameStart(IGameModeHandler gm)
		{
			TakeAllManager.ResetForNewGame();
			NestEggManager.ResetForNewGame();
			TakeAllVoteManager.ResetForNewGame();
			MercyTakeAllManager.ResetForNewGame();
			RoundWinTracker.Reset();
			AutoPickController.ResetForNewGame();
			KeysUnlockReset.Reapply();
			ExtensionMethods.ExecuteAfterSeconds((MonoBehaviour)(object)Instance, 0.35f, (Action)KeysUnlockReset.Reapply);
			yield break;
		}

		private static IEnumerator OnPlayerPickStart(IGameModeHandler gm)
		{
			FumbleController.ResetForPick();
			TakeAllManager.ClearAuthorization();
			TakeAllManager.ClearPickTransientState();
			TakeAllManager.ApplyDeferredKnowledge();
			TakeAllButton.RefreshVisibility();
			AutoPickController.NotifyPlayerPickStarted();
			Player picker = TakeAllManager.GetCurrentPicker();
			if ((Object)(object)picker != (Object)null)
			{
				ExtensionMethods.ExecuteAfterSeconds((MonoBehaviour)(object)Instance, 0.5f, (Action)delegate
				{
					MercyTakeAllManager.TryOfferMercy(picker);
				});
			}
			yield break;
		}

		private static IEnumerator OnPlayerPickEnd(IGameModeHandler gm)
		{
			FumbleController.ResetForPick();
			TakeAllVoteManager.CancelIfActive("Take All vote cancelled - pick ended.");
			TakeAllManager.ClearAuthorization();
			TakeAllManager.ClearActingPicker();
			TakeAllManager.ClearPickTransientState();
			PickAnnounceUi.HidePanic();
			TakeAllButton.RefreshVisibility();
			yield break;
		}

		private static IEnumerator OnPickEnd(IGameModeHandler gm)
		{
			FumbleController.ResetForPick();
			TakeAllVoteManager.CancelIfActive("Take All vote cancelled - pick ended.");
			TakeAllManager.ClearAuthorization();
			TakeAllManager.ClearActingPicker();
			TakeAllManager.ClearPickTransientState();
			PickAnnounceUi.HidePanic();
			TakeAllButton.Hide();
			CardBarMiniIcons.RestampAll();
			ExtensionMethods.ExecuteAfterSeconds((MonoBehaviour)(object)Instance, 0.25f, (Action)CardBarMiniIcons.RestampAll);
			ExtensionMethods.ExecuteAfterSeconds((MonoBehaviour)(object)Instance, 1f, (Action)CardBarMiniIcons.RestampAll);
			yield break;
		}

		private static void DrawSettingsMenu(GameObject menu)
		{
			MenuBuilder.Build(menu);
		}

		internal void Log(string message)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[Mulligan Madness] " + message));
		}

		internal void LogWarn(string message)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[Mulligan Madness] " + message));
		}
	}
	internal sealed class SessionVoteTicker : MonoBehaviour
	{
		private void Update()
		{
			TakeAllVoteManager.Tick();
		}
	}
}
namespace MulliganMadness.Utils
{
	public class AutoPickController : MonoBehaviour
	{
		private enum AutoPickMode
		{
			None,
			ForcedImmediate,
			PanicTimer,
			Leftmost
		}

		private static AutoPickController _instance;

		private Coroutine _running;

		private int _pickGeneration;

		private int _runningPlayerId = -1;

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

		public static void ResetForNewGame()
		{
			ResetForCurrentPick();
		}

		public static void ResetForCurrentPick()
		{
			if (!((Object)(object)_instance == (Object)null))
			{
				if (_instance._running != null)
				{
					((MonoBehaviour)_instance).StopCoroutine(_instance._running);
					_instance._running = null;
				}
				_instance._runningPlayerId = -1;
				_instance._pickGeneration++;
				PickAnnounceUi.HidePanic();
			}
		}

		public static void NotifyPlayerPickStarted()
		{
			if (!((Object)(object)_instance == (Object)null))
			{
				_instance.BeginForCurrentPick();
			}
		}

		private void BeginForCurrentPick()
		{
			Player currentPicker = TakeAllManager.GetCurrentPicker();
			if ((Object)(object)currentPicker == (Object)null || currentPicker.data?.currentCards == null || !LocalPlayerUtil.IsLocallyControlled(currentPicker))
			{
				return;
			}
			AutoPickMode autoPickMode = ResolveMode(currentPicker);
			if (autoPickMode != AutoPickMode.None && (_running == null || _runningPlayerId != currentPicker.playerID))
			{
				if (_running != null)
				{
					((MonoBehaviour)this).StopCoroutine(_running);
					_running = null;
				}
				_pickGeneration++;
				int pickGeneration = _pickGeneration;
				_runningPlayerId = currentPicker.playerID;
				_running = ((MonoBehaviour)this).StartCoroutine(RunAutoPick(currentPicker.playerID, autoPickMode, pickGeneration));
			}
		}

		private static AutoPickMode ResolveMode(Player player)
		{
			if (HasCurse(player, ForcedChoice.Card))
			{
				return AutoPickMode.ForcedImmediate;
			}
			if (HasCurse(player, LeftmostLuck.Card))
			{
				return AutoPickMode.Leftmost;
			}
			if (HasCurse(player, PanicPick.Card))
			{
				return AutoPickMode.PanicTimer;
			}
			return AutoPickMode.None;
		}

		private static bool HasCurse(Player player, CardInfo curse)
		{
			if (player?.data?.currentCards == null || (Object)(object)curse == (Object)null)
			{
				return false;
			}
			foreach (CardInfo currentCard in player.data.currentCards)
			{
				if (!((Object)(object)currentCard == (Object)null))
				{
					if ((Object)(object)currentCard == (Object)(object)curse)
					{
						return true;
					}
					if (!string.IsNullOrEmpty(curse.cardName) && string.Equals(currentCard.cardName, curse.cardName, StringComparison.OrdinalIgnoreCase))
					{
						return true;
					}
				}
			}
			return false;
		}

		private IEnumerator RunAutoPick(int playerID, AutoPickMode mode, int generation)
		{
			try
			{
				int safety = 12;
				while (safety-- > 0 && generation == _pickGeneration && WaitForOwnPick(playerID))
				{
					float timeout = 10f;
					while (timeout > 0f && generation == _pickGeneration)
					{
						if (TakeAllManager.IsBusy || !WaitForOwnPick(playerID))
						{
							yield break;
						}
						if (TakeAllManager.IsOfferedHandReady() && HandIsSelectable())
						{
							break;
						}
						timeout -= Time.unscaledDeltaTime;
						yield return null;
					}
					if (generation != _pickGeneration || !WaitForOwnPick(playerID))
					{
						break;
					}
					yield return WaitForFumbleIfNeeded(playerID, generation);
					if (generation != _pickGeneration || !WaitForOwnPick(playerID))
					{
						break;
					}
					if (mode == AutoPickMode.PanicTimer)
					{
						float wait = Mathf.Max(0.1f, SessionSettings.Current.PanicTimerSeconds);
						PickAnnounceUi.BroadcastPanic(playerID, wait);
						float elapsed = 0f;
						while (elapsed < wait && generation == _pickGeneration && WaitForOwnPick(playerID))
						{
							if (TakeAllManager.IsBusy)
							{
								PickAnnounceUi.HidePanic(broadcast: true);
								yield break;
							}
							List<GameObject> spawnedCards = TakeAllManager.GetSpawnedCards();
							if (spawnedCards == null || spawnedCards.Count == 0)
							{
								PickAnnounceUi.HidePanic(broadcast: true);
								yield break;
							}
							elapsed += Time.unscaledDeltaTime;
							yield return null;
						}
						PickAnnounceUi.HidePanic(broadcast: true);
						if (generation != _pickGeneration || !WaitForOwnPick(playerID))
						{
							break;
						}
					}
					List<GameObject> readySpawnedCards = TakeAllManager.GetReadySpawnedCards();
					if (readySpawnedCards == null || readySpawnedCards.Count == 0)
					{
						break;
					}
					GameObject val = SelectCard(readySpawnedCards, mode);
					if ((Object)(object)val == (Object)null || !readySpawnedCards.Contains(val))
					{
						yield return (object)new WaitForSecondsRealtime(0.1f);
						continue;
					}
					Plugin.Instance.Log($"Auto-pick ({mode}) for player {playerID}.");
					TryPick(val);
					GameObject picked = val;
					float settle = 2.5f;
					while (settle > 0f && generation == _pickGeneration)
					{
						yield return null;
						settle -= Time.unscaledDeltaTime;
						if (!WaitForOwnPick(playerID))
						{
							yield break;
						}
						List<GameObject> spawnedCards2 = TakeAllManager.GetSpawnedCards();
						if (spawnedCards2 == null || spawnedCards2.Count == 0 || !spawnedCards2.Contains(picked))
						{
							break;
						}
					}
					yield return (object)new WaitForSecondsRealtime(0.2f);
					if (WaitForOwnPick(playerID))
					{
						continue;
					}
					break;
				}
			}
			finally
			{
				AutoPickController autoPickController = this;
				if (generation == autoPickController._pickGeneration)
				{
					autoPickController._running = null;
					autoPickController._runningPlayerId = -1;
				}
			}
		}

		private static bool WaitForOwnPick(int playerID)
		{
			if ((Object)(object)CardChoice.instance == (Object)null || !CardChoice.instance.IsPicking)
			{
				return false;
			}
			Player currentPicker = TakeAllManager.GetCurrentPicker();
			if ((Object)(object)currentPicker != (Object)null)
			{
				return currentPicker.playerID == playerID;
			}
			return false;
		}

		private IEnumerator WaitForFumbleIfNeeded(int playerID, int generation)
		{
			Player val = TakeAllManager.FindPlayer(playerID) ?? TakeAllManager.GetCurrentPicker();
			if ((Object)(object)val == (Object)null || !CurseOwnership.Has(val, Fumble.Card))
			{
				yield break;
			}
			List<GameObject> spawnedCards = TakeAllManager.GetSpawnedCards();
			if (spawnedCards != null && spawnedCards.Count > 1)
			{
				float timeout = 1.25f;
				while (timeout > 0f && generation == _pickGeneration && WaitForOwnPick(playerID) && !FumbleController.HasRoll(playerID))
				{
					timeout -= Time.unscaledDeltaTime;
					yield return null;
				}
			}
		}

		private static GameObject SelectCard(List<GameObject> spawned, AutoPickMode mode)
		{
			if (spawned == null || spawned.Count == 0)
			{
				return null;
			}
			List<GameObject> list = spawned.FindAll((GameObject go) => (Object)(object)go != (Object)null);
			if (list.Count == 0)
			{
				return null;
			}
			switch (mode)
			{
			case AutoPickMode.Leftmost:
				return SelectLeftmost(list);
			case AutoPickMode.ForcedImmediate:
			case AutoPickMode.PanicTimer:
				return list[Random.Range(0, list.Count)];
			default:
				return null;
			}
		}

		private static GameObject SelectLeftmost(List<GameObject> spawned)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = null;
			float num = float.MaxValue;
			foreach (GameObject item in spawned)
			{
				if (!((Object)(object)item == (Object)null))
				{
					float x = item.transform.position.x;
					if (!(x >= num))
					{
						num = x;
						val = item;
					}
				}
			}
			return val ?? spawned[0];
		}

		private static bool HandIsSelectable()
		{
			List<GameObject> readySpawnedCards = TakeAllManager.GetReadySpawnedCards();
			List<GameObject> spawnedCards = TakeAllManager.GetSpawnedCards();
			if (readySpawnedCards == null || spawnedCards == null || readySpawnedCards.Count == 0)
			{
				return false;
			}
			return readySpawnedCards.Count >= spawnedCards.Count;
		}

		private static void TryPick(GameObject pick)
		{
			CardChoice instance = CardChoice.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)pick == (Object)null || !instance.IsPicking)
			{
				return;
			}
			List<GameObject> spawnedCards = TakeAllManager.GetSpawnedCards();
			if (spawnedCards == null || !spawnedCards.Contains(pick))
			{
				return;
			}
			try
			{
				instance.Pick(pick, false);
			}
			catch (Exception ex)
			{
				Plugin.Instance.LogWarn("Auto-pick Pick failed: " + ex.Message);
			}
		}
	}
	internal sealed class MmCardArtTag : MonoBehaviour
	{
		public string ArtName;
	}
	internal static class CardArtFactory
	{
		private static readonly HashSet<string> RegisteredCardNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, string> CardNameToArt = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<string> MissingMiniLogged = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<string> ArtNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static string _artFolder;

		private static bool _artFolderResolved;

		private static bool _artIndexBuilt;

		private static bool _folderLogged;

		private static Sprite _vanillaTemplateSprite;

		private static Type _nullCardInfoType;

		private static bool _nullCardInfoResolved;

		private static readonly Dictionary<string, Sprite> FullSprites = new Dictionary<string, Sprite>();

		private static readonly Dictionary<string, Sprite> MiniSprites = new Dictionary<string, Sprite>();

		private static readonly Dictionary<string, GameObject> Templates = new Dictionary<string, GameObject>();

		private static string DllDir => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "";

		private static string ArtFolder
		{
			get
			{
				if (_artFolderResolved)
				{
					return _artFolder;
				}
				_artFolderResolved = true;
				string dllDir = DllDir;
				string text = Path.Combine(dllDir, "Art");
				if (DirHasPng(text))
				{
					_artFolder = text;
				}
				else if (DirHasPng(dllDir))
				{
					_artFolder = dllDir;
				}
				else
				{
					string text2 = Path.Combine(Directory.GetParent(dllDir)?.FullName ?? dllDir, "Art");
					_artFolder = (DirHasPng(text2) ? text2 : text);
				}
				if (!_folderLogged)
				{
					_folderLogged = true;
					Plugin.Instance?.Log("Card art folder: " + _artFolder);
				}
				return _artFolder;
			}
		}

		internal static GameObject Create(string artName)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00c3: 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)
			//IL_00d9: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(artName))
			{
				return null;
			}
			if (Templates.TryGetValue(artName, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Sprite fullSprite = GetFullSprite(artName);
			if ((Object)(object)fullSprite == (Object)null)
			{
				return null;
			}
			GameObject val = new GameObject("MM_CardArt_" + artName, new Type[1] { typeof(RectTransform) });
			Object.DontDestroyOnLoad((Object)(object)val);
			val.AddComponent<MmCardArtTag>().ArtName = artName;
			Image obj = val.AddComponent<Image>();
			obj.sprite = fullSprite;
			obj.preserveAspect = true;
			((Graphic)obj).raycastTarget = false;
			((Graphic)obj).color = Color.white;
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.pivot = new Vector2(0.5f, 0.5f);
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			component.anchoredPosition = Vector2.zero;
			((Transform)component).localScale = Vector3.one;
			((Transform)component).localRotation = Quaternion.identity;
			CardArtFx.AttachToTemplate(val, artName);
			Templates[artName] = val;
			return val;
		}

		internal static Sprite GetMiniSprite(string artName)
		{
			//IL_00c9: 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)
			if (string.IsNullOrEmpty(artName))
			{
				return null;
			}
			if (MiniSprites.TryGetValue(artName, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			string text = ResolvePng(artName + "_mini.png") ?? ResolvePng(artName + ".png");
			if (text == null)
			{
				if (MissingMiniLogged.Add(artName))
				{
					Plugin.Instance?.LogWarn("No mini PNG for '" + artName + "' in " + ArtFolder + " or next to the DLL");
				}
				return null;
			}
			try
			{
				Texture2D val = LoadTexture(text);
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				MiniSprites[artName] = val2;
				return val2;
			}
			catch
			{
				return null;
			}
		}

		internal static bool IsNullPlaceholder(CardInfo card)
		{
			if ((Object)(object)card == (Object)null)
			{
				return false;
			}
			Type type = NullCardInfoType();
			if (type != null && type.IsInstanceOfType(card))
			{
				return true;
			}
			if (GameObjectHasNullCardInfo(((Component)card).gameObject))
			{
				return true;
			}
			string text = (card.cardName ?? "").Trim();
			if (text.StartsWith("[]", StringComparison.Ordinal))
			{
				return true;
			}
			if (text.Equals("null", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (text.Equals("NullCard", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (text.Equals("Null Card", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		internal static bool GameObjectHasNullCardInfo(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return false;
			}
			Type type = NullCardInfoType();
			if (type == null)
			{
				return false;
			}
			return (Object)(object)go.GetComponent(type) != (Object)null;
		}

		private static Type NullCardInfoType()
		{
			if (_nullCardInfoResolved)
			{
				return _nullCardInfoType;
			}
			_nullCardInfoResolved = true;
			_nullCardInfoType = AccessTools.TypeByName("Nullmanager.NullCardInfo");
			return _nullCardInfoType;
		}

		internal static void TryAssignSprite(CardInfo info)
		{
			try
			{
				if ((Object)(object)info == (Object)null || IsNullPlaceholder(info))
				{
					return;
				}
				string text = ArtNameFor(info);
				if (string.IsNullOrEmpty(text))
				{
					return;
				}
				RegisterCard(info, text);
				Sprite miniSprite = GetMiniSprite(text);
				if (!((Object)(object)miniSprite == (Object)null))
				{
					Sprite sprite = info.sprite;
					if ((Object)(object)_vanillaTemplateSprite == (Object)null && (Object)(object)sprite != (Object)null && (Object)(object)sprite != (Object)(object)miniSprite)
					{
						_vanillaTemplateSprite = sprite;
					}
					info.sprite = miniSprite;
					CardBarMiniIcons.AttachFancyIcon(info);
					StampPickIcons(info, miniSprite, sprite);
				}
			}
			catch (Exception ex)
			{
				Plugin.Instance?.LogWarn("TryAssignSprite skipped: " + ex.Message);
			}
		}

		internal static void RegisterCard(CardInfo info, string artName)
		{
			if (!((Object)(object)info == (Object)null) && !string.IsNullOrEmpty(artName) && !IsNullPlaceholder(info))
			{
				if (!string.IsNullOrEmpty(info.cardName))
				{
					RegisteredCardNames.Add(info.cardName);
					CardNameToArt[info.cardName] = artName;
				}
				MmCardArtTag mmCardArtTag = ((Component)info).GetComponent<MmCardArtTag>();
				if ((Object)(object)mmCardArtTag == (Object)null)
				{
					mmCardArtTag = ((Component)info).gameObject.AddComponent<MmCardArtTag>();
				}
				if (string.IsNullOrEmpty(mmCardArtTag.ArtName))
				{
					mmCardArtTag.ArtName = artName;
				}
			}
		}

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

		internal static string ArtNameFor(CardInfo info)
		{
			if ((Object)(object)info == (Object)null || IsNullPlaceholder(info))
			{
				return null;
			}
			MmCardArtTag component = ((Component)info).GetComponent<MmCardArtTag>();
			if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.ArtName))
			{
				return component.ArtName;
			}
			if ((Object)(object)info.cardArt != (Object)null)
			{
				MmCardArtTag component2 = info.cardArt.GetComponent<MmCardArtTag>();
				if ((Object)(object)component2 != (Object)null && !string.IsNullOrEmpty(component2.ArtName))
				{
					return component2.ArtName;
				}
			}
			if ((Object)(object)info.sourceCard != (Object)null && (Object)(object)info.sourceCard != (Object)(object)info)
			{
				string text = ArtNameFor(info.sourceCard);
				if (!string.IsNullOrEmpty(text))
				{
					return text;
				}
			}
			return GuessArtName(info.cardName);
		}

		internal static string GuessArtName(string cardName)
		{
			if (string.IsNullOrEmpty(cardName))
			{
				return null;
			}
			if (cardName.Trim().StartsWith("[]", StringComparison.Ordinal))
			{
				return null;
			}
			if (CardNameToArt.TryGetValue(cardName, out var value))
			{
				return value;
			}
			EnsureArtIndex();
			string text = Compact(cardName);
			if (ArtNames.Contains(text))
			{
				return text;
			}
			return null;
		}

		internal static void BindLoadedCardInfos()
		{
			CardInfo[] array = Resources.FindObjectsOfTypeAll<CardInfo>();
			for (int i = 0; i < array.Length; i++)
			{
				TryAssignSprite(array[i]);
			}
		}

		private static void StampPickIcons(CardInfo info, Sprite mini, Sprite oldSprite)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)info == (Object)null || (Object)(object)mini == (Object)null)
			{
				return;
			}
			Image[] componentsInChildren = ((Component)info).GetComponentsInChildren<Image>(true);
			foreach (Image val in componentsInChildren)
			{
				if (IsStampableImage(val) && SpriteMatches(val.sprite, mini, oldSprite))
				{
					ApplyMini(val, mini);
				}
			}
			SpriteRenderer[] componentsInChildren2 = ((Component)info).GetComponentsInChildren<SpriteRenderer>(true);
			foreach (SpriteRenderer val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).GetComponent<MmCardArtTag>() != (Object)null) && SpriteMatches(val2.sprite, mini, oldSprite))
				{
					val2.sprite = mini;
					val2.color = MmArtColorLock.ArtColor;
					if ((Object)(object)((Component)val2).GetComponent<MmArtColorLock>() == (Object)null)
					{
						((Component)val2).gameObject.AddComponent<MmArtColorLock>();
					}
				}
			}
			StampCornerCluster(info, mini);
		}

		private static void StampCornerCluster(CardInfo info, Sprite mini)
		{
			//IL_0091: 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_00a6: 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)
			Transform val = null;
			Transform[] componentsInChildren = ((Component)info).GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null && ((Object)val2).name == "EdgePart (2)")
				{
					val = val2;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Image val3 = null;
			Image[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Image>(true);
			foreach (Image val4 in componentsInChildren2)
			{
				if (!IsStampableImage(val4) || ((Object)((Component)val4).transform).name.StartsWith("EdgePart", StringComparison.Ordinal))
				{
					continue;
				}
				RectTransform rectTransform = ((Graphic)val4).rectTransform;
				Rect rect = rectTransform.rect;
				float num = Mathf.Abs(((Rect)(ref rect)).width);
				rect = rectTransform.rect;
				float num2 = Mathf.Abs(((Rect)(ref rect)).height);
				if (!(num > 140f) && !(num2 > 140f) && (!(num < 8f) || !(num2 < 8f)))
				{
					if ((Object)(object)val3 == (Object)null)
					{
						val3 = val4;
						ApplyMini(val4, mini);
					}
					else if (SpriteMatches(val4.sprite, mini, _vanillaTemplateSprite) || (Object)(object)val4.sprite == (Object)(object)val3.sprite)
					{
						((Behaviour)val4).enabled = false;
					}
				}
			}
		}

		private static bool IsStampableImage(Image img)
		{
			if ((Object)(object)img == (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)img).GetComponent<MmCardArtTag>() != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)img).GetComponent<MmMovingCardBackground>() != (Object)null)
			{
				return false;
			}
			string name = ((Object)((Component)img).gameObject).name;
			if (name.StartsWith("MM_", StringComparison.Ordinal))
			{
				return false;
			}
			if (name == "ModNameText")
			{
				return false;
			}
			return true;
		}

		private static bool SpriteMatches(Sprite current, Sprite mini, Sprite oldSprite)
		{
			if ((Object)(object)current == (Object)null)
			{
				return false;
			}
			if ((Object)(object)current == (Object)(object)mini)
			{
				return true;
			}
			if ((Object)(object)oldSprite != (Object)null && (Object)(object)current == (Object)(object)oldSprite)
			{
				return true;
			}
			if ((Object)(object)_vanillaTemplateSprite != (Object)null)
			{
				return (Object)(object)current == (Object)(object)_vanillaTemplateSprite;
			}
			return false;
		}

		private static void ApplyMini(Image img, Sprite mini)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			img.sprite = mini;
			img.overrideSprite = mini;
			img.preserveAspect = true;
			((Graphic)img).color = MmArtColorLock.ArtColor;
			((Behaviour)img).enabled = true;
			if ((Object)(object)((Component)img).GetComponent<MmArtColorLock>() == (Object)null)
			{
				((Component)img).gameObject.AddComponent<MmArtColorLock>();
			}
		}

		private static Sprite GetFullSprite(string artName)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (FullSprites.TryGetValue(artName, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			string text = ResolvePng(artName + ".png");
			if (text == null)
			{
				return null;
			}
			try
			{
				Texture2D val = LoadTexture(text);
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				FullSprites[artName] = val2;
				return val2;
			}
			catch
			{
				return null;
			}
		}

		private static string ResolvePng(string fileName)
		{
			string text = Path.Combine(ArtFolder, fileName);
			if (File.Exists(text))
			{
				return text;
			}
			string dllDir = DllDir;
			string text2 = Path.Combine(dllDir, fileName);
			if (File.Exists(text2))
			{
				return text2;
			}
			string text3 = Path.Combine(dllDir, "Art", fileName);
			if (File.Exists(text3))
			{
				return text3;
			}
			return null;
		}

		private static bool DirHasPng(string dir)
		{
			try
			{
				return Directory.Exists(dir) && Directory.GetFiles(dir, "*.png").Length != 0;
			}
			catch
			{
				return false;
			}
		}

		private static void EnsureArtIndex()
		{
			if (_artIndexBuilt)
			{
				return;
			}
			_artIndexBuilt = true;
			try
			{
				IndexDir(ArtFolder);
				IndexDir(DllDir);
				IndexDir(Path.Combine(DllDir, "Art"));
			}
			catch
			{
			}
		}

		private static void IndexDir(string dir)
		{
			if (string.IsNullOrEmpty(dir) || !Directory.Exists(dir))
			{
				return;
			}
			string[] files = Directory.GetFiles(dir, "*.png");
			for (int i = 0; i < files.Length; i++)
			{
				string text = Path.GetFileNameWithoutExtension(files[i]);
				if (!string.IsNullOrEmpty(text))
				{
					if (text.EndsWith("_mini", StringComparison.OrdinalIgnoreCase))
					{
						text = text.Substring(0, text.Length - 5);
					}
					ArtNames.Add(text);
				}
			}
		}

		private static string Compact(string s)
		{
			StringBuilder stringBuilder = new StringBuilder(s.Length);
			foreach (char c in s)
			{
				if (char.IsLetterOrDigit(c))
				{
					stringBuilder.Append(char.ToLowerInvariant(c));
				}
			}
			return stringBuilder.ToString();
		}

		private static Texture2D LoadTexture(string path)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			byte[] array = File.ReadAllBytes(path);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, array))
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			Object.DontDestroyOnLoad((Object)(object)val);
			return val;
		}
	}
	internal enum MmCardArtMotion
	{
		None,
		SubtleShake,
		EnergeticShake,
		Jitter
	}
	internal sealed class MmCardArtFxTag : MonoBehaviour
	{
		public MmCardArtMotion Motion;

		public bool MovingBackground;

		public float GlowScale;
	}
	internal sealed class MmArtColorLock : MonoBehaviour
	{
		internal static readonly Color ArtColor = new Color(0.82f, 0.82f, 0.82f, 1f);

		private Image _image;

		private void Awake()
		{
			_image = ((Component)this).GetComponent<Image>();
		}

		private void LateUpdate()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_image != (Object)null)
			{
				((Graphic)_image).color = ArtColor;
			}
		}
	}
	internal sealed class MmMovingCardBackground : CardAnimation
	{
		private const int BlobCount = 5;

		private Image[] _blobs;

		private Vector2[] _seeds;

		private Color _tint = new Color(1f, 0.55f, 0.15f, 0.05f);

		private bool _built;

		internal void SetTint(Color themeColor)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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)
			_tint = themeColor;
			_tint.a = 0.05f;
			if (_blobs == null)
			{
				return;
			}
			Image[] blobs = _blobs;
			foreach (Image val in blobs)
			{
				if ((Object)(object)val != (Object)null)
				{
					((Graphic)val).color = _tint;
				}
			}
		}

		private void OnEnable()
		{
			EnsureBuilt();
			SetBlobsVisible(on: true);
		}

		private void OnDisable()
		{
			SetBlobsVisible(on: false);
		}

		private void Update()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_00a1: 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_00c3: 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_00dd: 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_0101: 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)
			if (!_built || _blobs == null)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			for (int i = 0; i < _blobs.Length; i++)
			{
				Image val = _blobs[i];
				if (!((Object)(object)val == (Object)null))
				{
					Vector2 val2 = _seeds[i];
					RectTransform rectTransform = ((Graphic)val).rectTransform;
					float num = Mathf.Sin((unscaledTime + val2.x) * (0.35f + val2.y * 0.4f)) * 28f;
					float num2 = Mathf.Cos((unscaledTime * 0.7f + val2.y) * (0.4f + val2.x * 0.35f)) * 22f;
					rectTransform.anchoredPosition = new Vector2(num, num2);
					float num3 = 0.85f + 0.15f * Mathf.Sin(unscaledTime * (1.1f + val2.x) + val2.y);
					((Transform)rectTransform).localScale = Vector3.one * (0.7f + val2.x * 0.5f) * num3;
					Color tint = _tint;
					tint.a = _tint.a * (0.65f + 0.35f * num3);
					((Graphic)val).color = tint;
				}
			}
		}

		private void EnsureBuilt()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_00a0: 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_00ca: 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_00fb: 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_0165: 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)
			if (!_built)
			{
				_built = true;
				_blobs = (Image[])(object)new Image[5];
				_seeds = (Vector2[])(object)new Vector2[5];
				for (int i = 0; i < 5; i++)
				{
					GameObject val = new GameObject("MM_BgBlob_" + i, new Type[3]
					{
						typeof(RectTransform),
						typeof(CanvasRenderer),
						typeof(Image)
					});
					val.transform.SetParent(((Component)this).transform, false);
					val.transform.SetAsFirstSibling();
					RectTransform component = val.GetComponent<RectTransform>();
					component.anchorMin = new Vector2(0.5f, 0.5f);
					component.anchorMax = new Vector2(0.5f, 0.5f);
					component.pivot = new Vector2(0.5f, 0.5f);
					component.sizeDelta = new Vector2(220f + (float)i * 40f, 180f + (float)i * 30f);
					component.anchoredPosition = Vector2.zero;
					Image component2 = val.GetComponent<Image>();
					component2.sprite = SoftBlobSprite.Instance;
					component2.type = (Type)0;
					component2.preserveAspect = true;
					((Graphic)component2).raycastTarget = false;
					((Graphic)component2).color = _tint;
					_blobs[i] = component2;
					_seeds[i] = new Vector2(0.15f + (float)i * 0.17f, 0.4f + (float)(i % 3) * 0.2f);
				}
			}
		}

		private void SetBlobsVisible(bool on)
		{
			if (_blobs == null)
			{
				return;
			}
			Image[] blobs = _blobs;
			foreach (Image val in blobs)
			{
				if ((Object)(object)val != (Object)null)
				{
					((Behaviour)val).enabled = on;
				}
			}
		}
	}
	internal static class SoftBlobSprite
	{
		private static Sprite _sprite;

		internal static Sprite Instance
		{
			get
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Expected O, but got Unknown
				//IL_00d0: 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_0083: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_sprite != (Object)null)
				{
					return _sprite;
				}
				Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
				float num = 31.5f;
				for (int i = 0; i < 64; i++)
				{
					for (int j = 0; j < 64; j++)
					{
						float num2 = ((float)j - num) / num;
						float num3 = ((float)i - num) / num;
						float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
						float num5 = Mathf.Clamp01(1f - num4);
						num5 = num5 * num5 * (3f - 2f * num5);
						val.SetPixel(j, i, new Color(1f, 1f, 1f, num5));
					}
				}
				val.Apply(false, true);
				((Texture)val).filterMode = (FilterMode)1;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				Object.DontDestroyOnLoad((Object)(object)val);
				_sprite = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f);
				Object.DontDestroyOnLoad((Object)(object)_sprite);
				return _sprite;
			}
		}
	}
	internal static class CardArtFx
	{
		private struct FxSpec
		{
			internal MmCardArtMotion Motion;

			internal bool MovingBg;

			internal float Glow;

			internal FxSpec(MmCardArtMotion motion, bool movingBg, float glow)
			{
				Motion = motion;
				MovingBg = movingBg;
				Glow = glow;
			}
		}

		private static readonly Dictionary<string, FxSpec> Specs = new Dictionary<string, FxSpec>
		{
			["dynamite"] = new FxSpec(MmCardArtMotion.EnergeticShake, movingBg: false, 0f),
			["yeetcannon"] = new FxSpec(MmCardArtMotion.EnergeticShake, movingBg: false, 0f),
			["kickback"] = new FxSpec(MmCardArtMotion.EnergeticShake, movingBg: false, 0f),
			["tasertasertaser"] = new FxSpec(MmCardArtMotion.Jitter, movingBg: false, 0f),
			["fumble"] = new FxSpec(MmCardArtMotion.Jitter, movingBg: false, 0f),
			["bozoshoes"] = new FxSpec(MmCardArtMotion.SubtleShake, movingBg: false, 0f),
			["shove"] = new FxSpec(MmCardArtMotion.SubtleShake, movingBg: false, 0f),
			["thief"] = new FxSpec(MmCardArtMotion.SubtleShake, movingBg: false, 0f),
			["confetti"] = new FxSpec(MmCardArtMotion.SubtleShake, movingBg: false, 0f),
			["returntosender"] = new FxSpec(MmCardArtMotion.None, movingBg: false, 0f),
			["nestegg"] = new FxSpec(MmCardArtMotion.None, movingBg: false, 0f)
		};

		private const float DefaultGlow = 0f;

		internal static void AttachToTemplate(GameObject root, string artName)
		{
			if (!((Object)(object)root == (Object)null) && !string.IsNullOrEmpty(artName))
			{
				FxSpec fxSpec = Resolve(artName);
				MmCardArtFxTag mmCardArtFxTag = root.GetComponent<MmCardArtFxTag>() ?? root.AddComponent<MmCardArtFxTag>();
				mmCardArtFxTag.Motion = fxSpec.Motion;
				mmCardArtFxTag.MovingBackground = fxSpec.MovingBg;
				mmCardArtFxTag.GlowScale = fxSpec.Glow;
				if ((Object)(object)root.GetComponent<MmArtColorLock>() == (Object)null)
				{
					root.AddComponent<MmArtColorLock>();
				}
				if (!Specs.ContainsKey(artName))
				{
					mmCardArtFxTag.GlowScale = 0f;
				}
				ApplyMotion(root, fxSpec.Motion);
				if (fxSpec.MovingBg)
				{
					((Behaviour)(root.GetComponent<MmMovingCardBackground>() ?? root.AddComponent<MmMovingCardBackground>())).enabled = false;
				}
			}
		}

		internal static float GlowScaleFor(MmCardArtFxTag fx)
		{
			if (!((Object)(object)fx != (Object)null))
			{
				return 0f;
			}
			return Mathf.Clamp(fx.GlowScale, 0f, 0.28f);
		}

		private static FxSpec Resolve(string artName)
		{
			if (Specs.TryGetValue(artName, out var value))
			{
				return value;
			}
			return new FxSpec(MmCardArtMotion.None, movingBg: false, 0f);
		}

		private static void ApplyMotion(GameObject root, MmCardArtMotion motion)
		{
			PositionNoise component = root.GetComponent<PositionNoise>();
			if (motion == MmCardArtMotion.None)
			{
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				return;
			}
			PositionNoise val = component ?? root.AddComponent<PositionNoise>();
			((Behaviour)val).enabled = false;
			switch (motion)
			{
			case MmCardArtMotion.SubtleShake:
				val.amount = 4.5f;
				val.speed = 1.1f;
				break;
			case MmCardArtMotion.EnergeticShake:
				val.amount = 9f;
				val.speed = 2.2f;
				break;
			case MmCardArtMotion.Jitter:
				val.amount = 7f;
				val.speed = 4.5f;
				break;
			}
		}
	}
	internal static class CardBarMiniIcons
	{
		private const string ChildName = "MM_MiniIcon";

		private static readonly Dictionary<string, GameObject> FancyPrefabs = new Dictionary<string, GameObject>();

		private static GameObject _fancyHolder;

		private static Type _fancyIconType;

		private static bool _fancyResolved;

		private static readonly FieldInfo CardField = AccessTools.Field(typeof(CardBarButton), "card");

		internal static bool IsMmCard(CardInfo card)
		{
			if ((Object)(object)card == (Object)null || CardArtFactory.IsNullPlaceholder(card))
			{
				return false;
			}
			return !string.IsNullOrEmpty(CardArtFactory.ArtNameFor(card));
		}

		internal static void RestampAll()
		{
			CardBar[] array = Object.FindObjectsOfType<CardBar>();
			for (int i = 0; i < array.Length; i++)
			{
				ApplyAllMmOnBar(array[i]);
			}
		}

		internal static void ApplyToLatestButton(CardBar bar)
		{
			ApplyAllMmOnBar(bar);
		}

		internal static void ApplyAllMmOnBar(CardBar bar)
		{
			if ((Object)(object)bar == (Object)null)
			{
				return;
			}
			Transform transform = ((Component)bar).transform;
			for (int i = 0; i < transform.childCount; i++)
			{
				GameObject gameObject = ((Component)transform.GetChild(i)).gameObject;
				CardBarButton component = gameObject.GetComponent<CardBarButton>();
				if (!((Object)(object)component == (Object)null))
				{
					object? obj = CardField?.GetValue(component);
					CardInfo card = (CardInfo)((obj is CardInfo) ? obj : null);
					Apply(gameObject, card);
				}
			}
		}

		internal static void Apply(GameObject button, CardInfo card)
		{
			if ((Object)(object)button == (Object)null || (Object)(object)card == (Object)null)
			{
				return;
			}
			if (CardArtFactory.IsNullPlaceholder(card) || CardArtFactory.GameObjectHasNullCardInfo(button))
			{
				ClearMmStamp(button);
			}
			else
			{
				if (!IsMmCard(card))
				{
					return;
				}
				CardArtFactory.TryAssignSprite(card);
				AttachFancyIcon(card);
				Sprite val = SpriteFor(card);
				if (!((Object)(object)val == (Object)null))
				{
					TMP_Text[] componentsInChildren = button.GetComponentsInChildren<TMP_Text>(true);
					foreach (TMP_Text obj in componentsInChildren)
					{
						((Behaviour)obj).enabled = false;
						obj.text = "";
					}
					StripFancyOverlays(button);
					EnsureCleanOverlay(button, val);
					card.sprite = val;
				}
			}
		}

		internal static Sprite SpriteFor(CardInfo card)
		{
			if ((Object)(object)card == (Object)null)
			{
				return null;
			}
			string text = CardArtFactory.ArtNameFor(card);
			if (!string.IsNullOrEmpty(text))
			{
				Sprite miniSprite = CardArtFactory.GetMiniSprite(text);
				if ((Object)(object)miniSprite != (Object)null)
				{
					return miniSprite;
				}
			}
			if (!IsMmCard(card))
			{
				return null;
			}
			return card.sprite;
		}

		internal static void AttachFancyIcon(CardInfo info)
		{
			try
			{
				if ((Object)(object)info == (Object)null || !IsMmCard(info) || CardArtFactory.IsNullPlaceholder(info))
				{
					return;
				}
				Type type = FancyIconType();
				if (type == null)
				{
					return;
				}
				string text = CardArtFactory.ArtNameFor(info);
				if (string.IsNullOrEmpty(text))
				{
					return;
				}
				GameObject orCreateFancyPrefab = GetOrCreateFancyPrefab(text);
				if (!((Object)(object)orCreateFancyPrefab == (Object)null))
				{
					Component val = ((Component)info).gameObject.GetComponent(type);
					if ((Object)(object)val == (Object)null)
					{
						val = ((Component)info).gameObject.AddComponent(type);
					}
					AccessTools.Field(type, "fancyIcon")?.SetValue(val, orCreateFancyPrefab);
				}
			}
			catch (Exception ex)
			{
				Plugin.Instance?.LogWarn("AttachFancyIcon skipped: " + ex.Message);
			}
		}

		private static Type FancyIconType()
		{
			if (_fancyResolved)
			{
				return _fancyIconType;
			}
			_fancyResolved = true;
			_fancyIconType = AccessTools.TypeByName("FancyCardBar.FancyIcon");
			return _fancyIconType;
		}

		private static GameObject GetOrCreateFancyPrefab(string artName)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00c8: 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_00f2: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			if (FancyPrefabs.TryGetValue(artName, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Sprite miniSprite = CardArtFactory.GetMiniSprite(artName);
			if ((Object)(object)miniSprite == (Object)null)
			{
				return null;
			}
			if (!Object.op_Implicit((Object)(object)_fancyHolder))
			{
				_fancyHolder = new GameObject("MM_FancyBarIconHolder");
				Object.DontDestroyOnLoad((Object)(object)_fancyHolder);
				_fancyHolder.SetActive(false);
			}
			GameObject val = new GameObject("MM_FancyBarIcon_" + artName, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val.transform.SetParent(_fancyHolder.transform, false);
			val.SetActive(true);
			RectTransform component = val.GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(128f, 128f);
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.anchoredPosition = Vector2.zero;
			Image component2 = val.GetComponent<Image>();
			component2.sprite = miniSprite;
			component2.overrideSprite = miniSprite;
			component2.preserveAspect = true;
			((Graphic)component2).raycastTarget = false;
			((Graphic)component2).color = Color.white;
			FancyPrefabs[artName] = val;
			return val;
		}

		private static void StripFancyOverlays(GameObject button)
		{
			if ((Object)(object)button == (Object)null)
			{
				return;
			}
			MonoBehaviour[] componentsInChildren = button.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(((object)val).GetType().Name != "RGBColorShift"))
				{
					((Behaviour)val).enabled = false;
					if ((Object)(object)((Component)val).gameObject != (Object)(object)button)
					{
						((Component)val).gameObject.SetActive(false);
					}
				}
			}
			for (int num = button.transform.childCount - 1; num >= 0; num--)
			{
				Transform child = button.transform.GetChild(num);
				if (!((Object)(object)child == (Object)null) && !(((Object)child).name == "MM_MiniIcon") && !((Object)child).name.StartsWith("MM_FancyBarIcon_", StringComparison.Ordinal) && (Object)(object)((Component)child).GetComponentInChildren<MmCardArtTag>(true) != (Object)null)
				{
					((Component)child).gameObject.SetActive(false);
				}
			}
		}

		private static void EnsureCleanOverlay(GameObject button, Sprite sprite)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0078: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			Transform val = button.transform.Find("MM_MiniIcon");
			Image component2;
			if ((Object)(object)val == (Object)null)
			{
				GameObject val2 = new GameObject("MM_MiniIcon", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image)
				});
				val2.transform.SetParent(button.transform, false);
				RectTransform component = val2.GetComponent<RectTransform>();
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.one;
				component.pivot = new Vector2(0.5f, 0.5f);
				component.offsetMin = new Vector2(3f, 3f);
				component.offsetMax = new Vector2(-3f, -3f);
				component2 = val2.GetComponent<Image>();
				((Graphic)component2).raycastTarget = false;
				component2.preserveAspect = true;
			}
			else
			{
				component2 = ((Component)val).GetComponent<Image>();
				val.SetAsLastSibling();
			}
			if (!((Object)(object)component2 == (Object)null))
			{
				component2.sprite = sprite;
				component2.overrideSprite = sprite;
				((Graphic)component2).color = Color.white;
				((Behaviour)component2).enabled = true;
				((Component)component2).gameObject.SetActive(true);
			}
		}

		private static void ClearMmStamp(GameObject button)
		{
			if ((Object)(object)button == (Object)null)
			{
				return;
			}
			Transform val = button.transform.Find("MM_MiniIcon");
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(false);
			}
			for (int i = 0; i < button.transform.childCount; i++)
			{
				Transform child = button.transform.GetChild(i);
				if (!((Object)(object)child == (Object)null) && (((Object)child).name.StartsWith("MM_FancyBarIcon_", StringComparison.Ordinal) || (Object)(object)((Component)child).GetComponentInChildren<MmCardArtTag>(true) != (Object)null))
				{
					((Component)child).gameObject.SetActive(false);
				}
			}
			TMP_Text[] componentsInChildren = button.GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					((Behaviour)val2).enabled = true;
				}
			}
		}
	}
	internal static class CardEncoding
	{
		internal static string Encode(CardInfo card)
		{
			if ((Object)(object)card == (Object)null)
			{
				return "";
			}
			string obj = (((Object)(object)((Component)card).gameObject != (Object)null) ? StripClone(((Object)((Component)card).gameObject).name) : "");
			string text = card.cardName ?? "";
			return obj + "\n" + text;
		}

		internal static void Decode(string payload, out string objectName, out string cardName)
		{
			objectName = payload ?? "";
			cardName = "";
			if (!string.IsNullOrEmpty(payload))
			{
				int num = payload.IndexOf('\n');
				if (num >= 0)
				{
					objectName = payload.Substring(0, num);
					cardName = payload.Substring(num + 1);
				}
			}
		}

		internal static CardInfo Resolve(string payload)
		{
			Decode(payload, out var objectName, out var cardName);
			objectName = StripClone(objectName);
			CardInfo val = null;
			if (!string.IsNullOrEmpty(objectName))
			{
				try
				{
					val = Cards.instance.GetCardWithObjectName(objectName);
				}
				catch
				{
				}
			}
			if ((Object)(object)val == (Object)null && !string.IsNullOrEmpty(cardName))
			{
				try
				{
					val = Cards.instance.GetCardWithName(cardName);
				}
				catch
				{
				}
				if (val == null)
				{
					val = Cards.all?.FirstOrDefault((Func<CardInfo, bool>)((CardInfo c) => (Object)(object)c != (Object)null && !string.IsNullOrEmpty(c.cardName) && string.Equals(c.cardName, cardName, StringComparison.OrdinalIgnoreCase)));
				}
			}
			return val;
		}

		internal static string StripClone(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return name;
			}
			while (name.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				name = name.Substring(0, name.Length - "(Clone)".Length).Trim();
			}
			return name.Trim();
		}

		internal static bool Matches(CardInfo card, string payload)
		{
			if ((Object)(object)card == (Object)null || string.IsNullOrEmpty(payload))
			{
				return false;
			}
			Decode(payload, out var objectName, out var cardName);
			objectName = StripClone(objectName);
			if (!string.IsNullOrEmpty(objectName) && (Object)(object)((Component)card).gameObject != (Object)null && string.Equals(StripClone(((Object)((Component)card).gameObject).name), objectName, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (!string.IsNullOrEmpty(cardName))
			{
				return string.Equals(card.cardName, cardName, StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		internal static int FindCardIndex(Player player, string payload)
		{
			List<CardInfo> list = player?.data?.currentCards;
			if (list == null)
			{
				return -1;
			}
			for (int i = 0; i < list.Count; i++)
			{
				if (Matches(list[i], payload))
				{
					return i;
				}
			}
			return -1;
		}

		internal static Player FindHolder(string payload)
		{
			if (PlayerManager.instance?.players == null)
			{
				return null;
			}
			foreach (Player player in PlayerManager.instance.players)
			{
				if (!((Object)(object)player == (Object)null) && FindCardIndex(player, payload) >= 0)
				{
					return player;
				}
			}
			return null;
		}
	}
	internal static class CardPool
	{
		private static MethodInfo _isCardActive;

		internal static bool IsActive(CardInfo card)
		{
			if ((Object)(object)card == (Object)null)
			{
				return false;
			}
			try
			{
				if ((object)_isCardActive == null)
				{
					_isCardActive = AccessTools.Method(AccessTools.TypeByName("UnboundLib.Utils.CardManager"), "IsCardActive", (Type[])null, (Type[])null);
				}
				if (_isCardActive == null)
				{
					return true;
				}
				object obj = card;
				ParameterInfo[] parameters = _isCardActive.GetParameters();
				if (parameters.Length == 1 && parameters[0].ParameterType == typeof(string))
				{
					obj = (((Object)(object)((Component)card).gameObject != (Object)null) ? CardEncoding.StripClone(((Object)((Component)card).gameObject).name) : card.cardName);
				}
				if (_isCardActive.Invoke(null, new object[1] { obj }) is bool result)
				{
					return result;
				}
			}
			catch
			{
			}
			return true;
		}
	}
	internal static class CardStatApply
	{
		internal static CardInfoStat Stat(bool positive, string stat, string amount)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			return new CardInfoStat
			{
				positive = positive,
				stat = stat,
				amount = amount,
				simepleAmount = (SimpleAmount)0
			};
		}

		internal static void AddAmmo(Gun gun, int amount)
		{
			if (!((Object)(object)gun == (Object)null))
			{
				gun.ammo = amount;
				GunAmmo val = ((Component)gun).GetComponent<GunAmmo>() ?? ((Component)gun).GetComponentInChildren<GunAmmo>(true);
				if ((Object)(object)val != (Object)null)
				{
					val.maxAmmo = amount;
				}
			}
		}
	}
	internal static class CardTargetUi
	{
		private sealed class ToastHost : MonoBehaviour
		{
			private TextMeshProUGUI _label;

			private CanvasGroup _group;

			private Image _bg;

			private RectTransform _rect;

			internal void Build()
			{
				//IL_0021: 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_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: 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_00f7: Expected O, but got Unknown
				//IL_010f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0114: 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_0169: Unknown result type (might be due to invalid IL or missing references)
				//IL_016f: Expected O, but got Unknown
				//IL_0191: 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_01c5: 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_01f3: Expected O, but got Unknown
				//IL_020c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0217: Unknown result type (might be due to invalid IL or missing references)
				//IL_022c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0240: 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)
				_rect = ((Component)this).gameObject.GetComponent<RectTransform>();
				_rect.anchorMin = new Vector2(0.5f, 1f);
				_rect.anchorMax = new Vector2(0.5f, 1f);
				_rect.pivot = new Vector2(0.5f, 1f);
				_rect.anchoredPosition = new Vector2(0f, -28f);
				_rect.sizeDelta = new Vector2(720f, 56f);
				_group = ((Component)this).gameObject.AddComponent<CanvasGroup>();
				_group.blocksRaycasts = false;
				_group.interactable = false;
				_group.alpha = 0f;
				GameObject val = new GameObject("Border", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				val.transform.SetParent(((Component)this).transform, false);
				MmUiGfx.Stretch(val.GetComponent<RectTransform>(), Vector2.zero, Vector2.zero);
				MmUiGfx.Solid(val.GetComponent<Image>(), new Color(0.95f, 0.82f, 0.35f, 1f));
				GameObject val2 = new GameObject("Fill", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				val2.transform.SetParent(val.transform, false);
				MmUiGfx.Stretch(val2.GetComponent<RectTransform>(), new Vector2(3f, 3f), new Vector2(-3f, -3f));
				_bg = MmUiGfx.Solid(val2.GetComponent<Image>(), new Color(0.06f, 0.1f, 0.08f, 0.92f));
				GameObject val3 = new GameObject("Label", new Type[1] { typeof(RectTransform) });
				val3.transform.SetParent(val2.transform, false);
				RectTransform component = val3.GetComponent<RectTransform>();
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.one;
				component.offsetMin = new Vector2(16f, 8f);
				component.offsetMax = new Vector2(-16f, -8f);
				_label = val3.AddComponent<TextMeshProUGUI>();
				((TMP_Text)_label).alignment = (TextAlignmentOptions)514;
				((TMP_Text)_label).fontSize = 20f;
				((TMP_Text)_label).fontStyle = (FontStyles)1;
				((Graphic)_label).color = new Color(1f, 0.95f, 0.82f, 1f);
				((Graphic)_label).raycastTarget = false;
				((TMP_Text)_label).enableWordWrapping = false;
				((TMP_Text)_label).overflowMode = (TextOverflowModes)0;
			}

			internal void Show(string message)
			{
				//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_label == (Object)null) && !string.IsNullOrWhiteSpace(message))
				{
					((Component)this).gameObject.SetActive(true);
					((TMP_Text)_label).text = message;
					((TMP_Text)_label).enableWordWrapping = false;
					((TMP_Text)_label).ForceMeshUpdate();
					Canvas.ForceUpdateCanvases();
					if ((Object)(object)_rect != (Object)null)
					{
						float num = ((TMP_Text)_label).preferredWidth + 32f;
						float num2 = Mathf.Max(32f, ((TMP_Text)_label).preferredHeight) + 16f;
						_rect.sizeDelta = new Vector2(Mathf.Clamp(num + 6f, 280f, 980f), num2 + 6f);
					}
					_group.alpha = 1f;
					((MonoBehaviour)this).CancelInvoke("Hide");
					((MonoBehaviour)this).Invoke("Hide", 3f);
				}
			}

			private void Hide()
			{
				if ((Object)(object)_group != (Object)null)
				{
					_group.alpha = 0f;
				}
			}
		}

		private class Overlay : MonoBehaviour
		{
			private RectTransform _panel;

			private TextMeshProUGUI _title;

			private TextMeshProUGUI _subtitle;

			private Transform _playerGrid;

			private Button _confirmButton;

			private Button _cancelButton;

			private Player _actor;

			private Player _selected;

			private Action<Player> _onConfirm;

			private string _confirmLabel;

			internal void Build(Transform canvasRoot)
			{
				//IL_000c: 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_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: 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_009d: 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_00f2: 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_0147: Unknown result type (might be due to invalid IL or missing references)
				//IL_0169: Unknown result type (might be due to invalid IL or missing references)
				//IL_016f: Expected O, but got Unknown
				//IL_019e: 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_01c8: 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_01f7: Unknown result type (might be due to invalid IL or missing references)
				//IL_020c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0239: Unknown result type (might be due to invalid IL or missing references)
				//IL_026c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0292: Unknown result type (might be due to invalid IL or missing references)
				//IL_029c: Expected O, but got Unknown
				RectTransform component = ((Component)this).gameObject.GetComponent<RectTransform>();
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.one;
				component.offsetMin = Vector2.zero;
				component.offsetMax = Vector2.zero;
				((Graphic)CreateImage("Dim", ((Component)this).transform, Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero)).color = new Color(0f, 0f, 0f, 0.72f);
				_panel = CreatePanel("Panel", ((Component)this).transform, new Vector2(0.5f, 0.5f), new Vector2(680f, 520f));
				MmUiGfx.Solid(((Component)_panel).gameObject.AddComponent<Image>(), new Color(0.08f, 0.12f, 0.1f, 0.98f));
				_title = CreateText("Title", (Transform)(object)_panel, new Vector2(24f, -20f), 30f, (FontStyles)1);
				_subtitle = CreateText("Subtitle", (Transform)(object)_panel, new Vector2(24f, -58f), 18f, (FontStyles)0);
				((Graphic)_subtitle).color = new Color(0.85f, 0.88f, 0.82f);
				GameObject val = new GameObject("PlayerGrid", new Type[1] { typeof(RectTransform) });
				val.transform.SetParent((Transform)(object)_panel, false);
				_playerGrid = val.transform;
				RectTransform component2 = val.GetComponent<RectTransform>();
				component2.anchorMin = new Vector2(0f, 0.22f);
				component2.anchorMax = new Vector2(1f, 0.78f);
				component2.offsetMin = new Vector2(24f, 0f);
				component2.offsetMax = new Vector2(-24f, 0f);
				GridLayoutGroup obj = val.AddComponent<GridLayoutGroup>();
				obj.cellSize = new Vector2(190f, 72f);
				obj.spacing = new Vector2(12f, 12f);
				obj.constraint = (Constraint)1;
				obj.constraintCount = 2;
				_confirmButton = CreateButton("Confirm", (Transform)(object)_panel, new Vector2(0.56f, 0.08f), _confirmLabel = "CONFIRM");
				_cancelButton = CreateButton("Cancel", (Transform)(object)_panel, new Vector2(0.08f, 0.08f), "CANCEL");
				((UnityEvent)_cancelButton.onClick).AddListener(new UnityAction(Close));
			}

			internal void OpenTargetOnly(Player actor, string title, string subtitle, string confirmLabel, Action<Player> onConfirm, bool includeSelf = true)
			{
				_actor = actor;
				_onConfirm = onConfirm;
				_confirmLabel = confirmLabel;
				((TMP_Text)_title).text = title;
				((TMP_Text)_subtitle).text = subtitle;
				((TMP_Text)((Component)_confirmButton).GetComponentInChildren<TextMeshProUGUI>()).text = confirmLabel;
				_selected = (includeSelf ? actor : null);
				RebuildPlayerButtons(includeSelf, filterStealable: false);
				((Component)this).gameObject.SetActive(true);
			}

			internal void OpenCardChoices(string title, string subtitle, string confirmLabel, List<(string label, GameObject card)> cards, Action<GameObject> onConfirm, Action onCancel)
			{
				//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d6: Expected O, but got Unknown
				//IL_0111: Unknown result type (might be due to invalid IL or missing references)
				//IL_011b: Expected O, but got Unknown
				//IL_013d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0147: Expected O, but got Unknown
				_actor = null;
				_onConfirm = null;
				_confirmLabel = confirmLabel;
				((TMP_Text)_title).text = title;
				((TMP_Text)_subtitle).text = subtitle;
				((TMP_Text)((Component)_confirmButton).GetComponentInChildren<TextMeshProUGUI>()).text = confirmLabel;
				_selected = null;
				ClearGrid();
				GameObject picked = null;
				foreach (var card in cards)
				{
					if ((Object)(object)card.card == (Object)null)
					{
						continue;
					}
					Button button = CreateLabeledButton(card.label);
					GameObject captured = card.card;
					((UnityEvent)button.onClick).AddListener((UnityAction)delegate
					{
						//IL_002f: 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_009c: Unknown result type (might be due to invalid IL or missing references)
						picked = captured;
						foreach (Transform item in _playerGrid)
						{
							Image component = ((Component)item).GetComponent<Image>();
							if ((Object)(object)component != (Object)null)
							{
								((Graphic)component).color = new Color(0.14f, 0.2f, 0.16f, 1f);
							}
						}
						((Graphic)((Component)button).GetComponent<Image>()).color = new Color(0.18f, 0.48f, 0.3f, 1f);
					});
				}
				((UnityEventBase)_confirmButton.onClick).RemoveAllListeners();
				((UnityEvent)_confirmButton.onClick).AddListener((UnityAction)delegate
				{
					if (!((Object)(object)picked == (Object)null))
					{
						onConfirm?.Invoke(picked);
						Close();
					}
				});
				((UnityEventBase)_cancelButton.onClick).RemoveAllListeners();
				((UnityEvent)_cancelButton.onClick).AddListener((UnityAction)delegate
				{
					onCancel?.Invoke();
					Close();
				});
				((Component)this).gameObject.SetActive(true);
			}

			internal void Close()
			{
				((Component)this).gameObject.SetActive(false);
				ClearGrid();
			}

			private void RebuildPlayerButtons(bool includeSelf, bool filterStealable)
			{
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f7: Expected O, but got Unknown
				//IL_0119: Unknown result type (might be due to invalid IL or missing references)
				//IL_0123: Expected O, but got Unknown
				//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00af: Expected O, but got Unknown
				ClearGrid();
				if (PlayerManager.instance?.players == null)
				{
					return;
				}
				foreach (Player player in PlayerManager.instance.players)
				{
					if (!((Object)(object)player == (Object)null) && (includeSelf || !((Object)(object)_actor != (Object)null) || player.playerID != _actor.playerID))
					{
						int stealable = 0;
						string label = BuildPlayerLabel(player, stealable, filterStealable);
						Button button = CreateGridButton(label, player);
						Player captured = player;
						((UnityEvent)button.onClick).AddListener((UnityAction)delegate
						{
							SelectPlayer(captured, button);
						});
					}
				}
				((UnityEventBase)_confirmButton.onClick).RemoveAllListeners();
				((UnityEvent)_confirmButton.onClick).AddListener((UnityAction)delegate
				{
					if (!((Object)(object)_selected == (Object)null))
					{
						_onConfirm?.Invoke(_selected);
						Close();
					}
				});
				((UnityEventBase)_cancelButton.onClick).RemoveAllListeners();
				((UnityEvent)_cancelButton.onClick).AddListener(new UnityAction(Close));
			}

			private void SelectPlayer(Player player, Button button)
			{
				//IL_001b: 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_0083: Unknown result type (might be due to invalid IL or missing references)
				_selected = player;
				foreach (Transform item in _playerGrid)
				{
					Image component = ((Component)item).GetComponent<Image>();
					if ((Object)(object)component != (Object)null)
					{
						((Graphic)component).color = new Color(0.14f, 0.2f, 0.16f, 1f);
					}
				}
				((Graphic)((Component)button).GetComponent<Image>()).color = new Color(0.18f, 0.48f, 0.3f, 1f);
			}

			private Button CreateLabeledButton(string label)
			{
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Expected O, but got Unknown
				//IL_0064: 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_0094: 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_00ad: 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_00cd: 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_010d: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = new GameObject("Choice", new Type[3]
				{
					typeof(RectTransform),
					typeof(Image),
					typeof(Button)
				});
				val.transform.SetParent(_playerGrid, false);
				MmUiGfx.Solid(val.GetComponent<Image>(), new Color(0.14f, 0.2f, 0.16f, 1f), raycast: true);
				Button component = val.GetComponent<Button>();
				GameObject val2 = new GameObject("Label", new Type[1] { typeof(RectTransform) });
				val2.transform.SetParent(val.transform, false);
				RectTransform component2 = val2.GetComponent<RectTransform>();
				component2.anchorMin = Vector2.zero;
				component2.anchorMax = Vector2.one;
				component2.offsetMin = new Vector2(8f, 4f);
				component2.offsetMax = new Vector2(-8f, -4f);
				TextMeshProUGUI obj = val2.AddComponent<TextMeshProUGUI>();
				((TMP_Text)obj).text = label;
				((TMP_Text)obj).fontSize = 16f;
				((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
				((Graphic)obj).color = Color.white;
				return component;
			}

			private Button CreateGridButton(string label, Player player)
			{
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Expected O, but got Unknown
				//IL_0095: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f2: 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_0104: Unknown result type (might be due to invalid IL or missing references)
				//IL_0119: 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_0159: 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)
				GameObject val = new GameObject("Player_" + player.playerID, new Type[3]
				{
					typeof(RectTransform),
					typeof(Image),
					typeof(Button)
				});
				val.transform.SetParent(_playerGrid, false);
				MmUiGfx.Solid(val.GetComponent<Image>(), ((Object)(object)_selected != (Object)null && _selected.playerID == player.playerID) ? new Color(0.18f, 0.48f, 0.3f, 1f) : new Color(0.14f, 0.2f, 0.16f, 1f), raycast: true);
				Button component = val.GetComponent<Button>();
				GameObject val2 = new GameObject("Label", new Type[1] { typeof(RectTransform) });
				val2.transform.SetParent(val.transform, false);
				RectTransform component2 = val2.GetComponent<RectTransform>();
				component2.anchorMin = Vector2.zero;
				component2.anchorMax = Vector2.one;
				component2.offsetMin = new Vector2(8f, 4f);
				component2.offsetMax = new Vector2(-8f, -4f);
				TextMeshProUGUI obj = val2.AddComponent<TextMeshProUGUI>();
				((TMP_Text)obj).text = label;
				((TMP_Text)obj).fontSize = 16f;
				((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
				((Graphic)obj).color = Color.white;
				return component;
			}

			private static string BuildPlayerLabel(Player player, int stealable, bool showStealable)
			{
				CharacterData data = player.data;
				object obj;
				if (data == null)
				{
					obj = null;
				}
				else
				{
					PhotonView view = data.view;
					if (view == null)
					{
						obj = null;
					}
					else
					{
						Player owner = view.Owner;
						obj = ((owner != null) ? owner.NickName : null);
					}
				}
				string text = (string)obj;
				if (string.IsNullOrEmpty(text))
				{
					text = "Player " + (player.playerID + 1);
				}
				if (!showStealable)
				{
					return text;
				}
				if (stealable <= 0)
				{
					return text + "\nno cards";
				}
				return $"{text}\n{stealable} stealable";
			}

			private void ClearGrid()
			{
				if (!((Object)(object)_playerGrid == (Object)null))
				{
					for (int num = _playerGrid.childCount - 1; num >= 0; num--)
					{
						Object.Destroy((Object)(object)((Component)_playerGrid.GetChild(num)).gameObject);
					}
				}
			}

			private static RectTransform CreatePanel(string name, Transform parent, Vector2 anchor, Vector2 size)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: 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_0056: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
				val.transform.SetParent(parent, false);
				RectTransform component = val.GetComponent<RectTransform>();
				component.anchorMin = anchor;
				component.anchorMax = anchor;
				component.pivot = new Vector2(0.5f, 0.5f);
				component.sizeDelta = size;
				component.anchoredPosition = Vector2.zero;
				return component;
			}

			private static Image CreateImage(string name, Transform parent, Vector2 min, Vector2 max, Vector2 offsetMin, Vector2 offsetMax)
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_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_004f: 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)
				GameObject val = new GameObject(name, new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				val.transform.SetParent(parent, false);
				RectTransform component = val.GetComponent<RectTransform>();
				component.anchorMin = min;
				component.anchorMax = max;
				component.offsetMin = offsetMin;
				component.offsetMax = offsetMax;
				return MmUiGfx.Solid(val.GetComponent<Image>(), Color.white);
			}

			private static TextMeshProUGUI CreateText(string name, Transform parent, Vector2 anchoredPos, float size, FontStyles style)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: 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_004c: 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_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0093: 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)
				GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
				val.transform.SetParent(parent, false);
				RectTransform component = val.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0f, 1f);
				component.anchorMax = new Vector2(1f, 1f);
				component.pivot = new Vector2(0f, 1f);
				component.anchoredPosition = anchoredPos;
				component.sizeDelta = new Vector2(-48f, 32f);
				TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
				((TMP_Text)obj).fontSize = size;
				((TMP_Text)obj).fontStyle = style;
				((Graphic)obj).color = Color.white;
				return obj;
			}

			private static Button CreateButton(string name, Transform parent, Vector2 anchorMin, string label)
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Expected O, but got Unknown
				//IL_0048: 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_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: 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_00ce: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
				//IL_0102: 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)
				GameObject val = new GameObject(name, new Type[3]
				{
					typeof(RectTransform),
					typeof(Image),
					typeof(Button)
				});
				val.transform.SetParent(parent, false);
				RectTransform component = val.GetComponent<RectTransform>();
				component.anchorMin = anchorMin;
				component.anchorMax = anchorMin;
				component.pivot = new Vector2(0f, 0f);
				component.sizeDelta = new Vector2(260f, 48f);
				component.anchoredPosition = Vector2.zero;
				MmUiGfx.Solid(val.GetComponent<Image>(), new Color(0.12f, 0.42f, 0.28f, 1f), raycast: true);
				Button component2 = val.GetComponent<Button>();
				GameObject val2 = new GameObject("Label", new Type[1] { typeof(RectTransform) });
				val2.transform.SetParent(val.transform, false);
				RectTransform component3 = val2.GetComponent<RectTransform>();
				component3.anchorMin = Vector2.zero;
				component3.anchorMax = Vector2.one;
				component3.offsetMin = Vector2.zero;
				component3.offsetMax = Vector2.zero;
				TextMeshProUGUI obj = val2.AddComponent<TextMeshProUGUI>();
				((TMP_Text)obj).text = label;
				((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
				((TMP_Text)obj).fontSize = 18f;
				((TMP_Text)obj).fontStyle = (FontStyles)1;
				return component2;
			}
		}

		private static Overlay _overlay;

		private static ToastHost _toast;

		internal static bool IsOpen
		{
			get
			{
				if ((Object)(object)_overlay != (Object)null)
				{
					return ((Component)_overlay).gameObject.activeSelf;
				}
				return false;
			}
		}

		internal static void OpenSandbag(Player user, Action<Player> onConfirm)
		{
			OpenPlayerTarget(user, "Sandbag Simulator", "Choose who rerolls their current pick hand.", "REROLL HAND", onConfirm, includeSelf: true);
		}

		internal static void OpenPlayerTarget(Player user, string title, string subtitle, string confirmLabel, Action<Player> onConfirm, bool includeSelf)
		{
			EnsureOverlay();
			_overlay.OpenTargetOnly(user, title, subtitle, confirmLabel, onConfirm, includeSelf);
		}

		internal static void OpenCardChoices(string title, string subtitle, string confirmLabel, List<(string label, GameObject card)> cards, Action<GameObject> onConfirm, Action onCancel = null)
		{
			EnsureOverlay();
			_overlay.OpenCardChoices(title, subtitle, confirmLabel, cards, onConfirm, onCancel);
		}

		internal static void ShowToast(string message)
		{
			EnsureToast();
			_toast?.Show(message);
		}

		internal static void Close()
		{
			if ((Object)(object)_overlay != (Object)null)
			{
				_overlay.Close();
			}
		}

		private static void EnsureOverlay()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_overlay != (Object)null))
			{
				Unbound instance = Unbound.Instance;
				Canvas val = ((instance != null) ? instance.canvas : null);
				if (!((Object)(object)val == (Object)null))
				{
					GameObject val2 = new GameObject("MM_CardTargetUi", new Type[1] { typeof(RectTransform) });
					val2.transform.SetParent(((Component)val).transform, false);
					_overlay = val2.AddComponent<Overlay>();
					_overlay.Build(((Component)val).transform);
					val2.SetActive(false);
				}
			}
		}

		private static void EnsureToast()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_toast != (Object)null))
			{
				Unbound instance = Unbound.Instance;
				Canvas val = ((instance != null) ? instance.canvas : null);
				if (!((Object)(object)val == (Object)null))
				{
					GameObject val2 = new GameObject("MM_Toast", new Type[1] { typeof(RectTransform) });
					val2.transform.SetParent(((Component)val).transform, false);
					_toast = val2.AddComponent<ToastHost>();
					_toast.Build();
					val2.SetActive(true);
				}
			}
		}
	}
	public class Configs
	{
		public ConfigEntry<TakeAllMode> DefaultTakeAllMode { get; }

		public ConfigEntry<int> DefaultTakeAllUsesPerPlayer { get; }

		public ConfigEntry<float> DefaultVoteThreshold { get; }

		public ConfigEntry<float> DefaultVoteTimeoutSeconds { get; }

		public ConfigEntry<bool> DefaultVoteConsumesUse { get; }

		public ConfigEntry<bool> DefaultTakeAllCurseCost { get; }

		public ConfigEntry<TakeAllCurseOnExisting> DefaultCurseOnExisting { get; }

		public ConfigEntry<bool> DefaultEnableMercyVote { get; }

		public ConfigEntry<int> DefaultMercyRoundDeficit { get; }

		public ConfigEntry<bool> DefaultMercyOncePerGame { get; }

		public ConfigEntry<bool> EnableAutoPickCurses { get; }

		public ConfigEntry<float> PanicTimerSeconds { get; }

		public ConfigEntry<bool> FixPristineHealth { get; }

		public ConfigEntry<bool> EnableThiefCard { get; }

		public ConfigEntry<bool> EnableTakebacksies { get; }

		public ConfigEntry<bool> EnableSandbagSimulator { get; }

		public ConfigEntry<bool> EnableJarOfDirt { get; }

		public ConfigEntry<bool> SandbagOncePerGame { get; }

		public ConfigEntry<bool> LogPickPhase { get; }

		public ConfigEntry<bool> EnableStatsHud { get; }

		public ConfigEntry<bool> StatsHudVisible { get; }

		public ConfigEntry<bool> StatsHudCollapsed { get; }

		public ConfigEntry<bool> StatsHudSimpleMode { get; }

		public ConfigEntry<bool> StatsHudUltraCompact { get; }

		public ConfigEntry<bool> StatsHudPeekMode { get; }

		public ConfigEntry<KeyCode> StatsHudPeekKey { get; }

		public ConfigEntry<bool> HideStatsHudDuringPick { get; }

		public ConfigEntry<bool> HideStatsHudDuringBattle { get; }

		public ConfigEntry<KeyCode> StatsHudToggleKey { get; }

		public ConfigEntry<float> StatsHudOpacity { get; }

		public ConfigEntry<float> StatsHudFontScale { get; }

		public ConfigEntry<float> StatsHudColorR { get; }

		public ConfigEntry<float> StatsHudColorG { get; }

		public ConfigEntry<float> StatsHudColorB { get; }

		public ConfigEntry<bool> EnableStatsTab { get; }

		public ConfigEntry<bool> EnableTabCompare { get; }

		public ConfigEntry<float> TabPanelWidth { get; }

		public ConfigEntry<float> TabPanelHeightFraction { get; }

		public ConfigEntry<float> TabPanelOpacity { get; }

		public ConfigEntry<bool> TabAnchorLeft { get; }

		public ConfigEntry<float> TabPosX { get; }

		public ConfigEntry<float> TabPosY { get; }

		public ConfigEntry<bool> ShowPing { get; }

		public ConfigEntry<bool> ShowPickDeltasOnHud { get; }

		public ConfigEntry<float> StatsPanelScale { get; }

		public ConfigEntry<float> StatsHudOffsetX { get; }

		public ConfigEntry<float> StatsHudOffsetY { get; }

		public ConfigEntry<float> StatsAccentR { get; }

		public ConfigEntry<float> StatsAccentG { get; }

		public ConfigEntry<float> StatsAccentB { get; }

		public ConfigEntry<bool> AutoCloseTabDuringPick { get; }

		public Configs(ConfigFile config)
		{
			DefaultTakeAllMode = config.Bind<TakeAllMode>("Session Defaults", "TakeAllMode", TakeAllMode.OncePerGame, "0=Disabled, 1=Once per game, 2=Multi-use, 3=Vote");
			DefaultTakeAllUsesPerPlayer = config.Bind<int>("Session Defaults", "TakeAllUsesPerPlayer", 1, "Take All uses per player per game (0-3).");
			DefaultVoteThreshold = config.Bind<float>("Session Defaults", "VoteThreshold", 0.5f, "Fraction of voters who must accept (excluding requester).");
			DefaultVoteTimeoutSeconds = config.Bind<float>("Session Defaults", "VoteTimeoutSeconds", 15f, "Seconds before a Take All vote expires.");
			DefaultVoteConsumesUse = config.Bind<bool>("Session Defaults", "VoteConsumesUse", true, "Whether a passed vote consumes a Take All use.");
			DefaultTakeAllCurseCost = config.Bind<bool>("Session Defaults", "TakeAllCurseCost", false, "Take All grants a random Mulligan Madness auto-pick curse afterward.");
			DefaultCurseOnExisting = config.Bind<TakeAllCurseOnExisting>("Session Defaults", "CurseOnExisting", TakeAllCurseOnExisting.ReplaceExisting, "0=Replace existing MulliganMadness curse, 1=Skip curse if player already has one.");
			DefaultEnableMercyVote = config.Bind<bool>("Session Defaults", "EnableMercyVote", false, "Auto-offer a Take All vote when a player is down by MercyRoundDeficit round wins.");
			DefaultMercyRoundDeficit = config.Bind<int>("Session Defaults", "MercyRoundDeficit", 2, "Round-win deficit vs the leader before mercy vote can trigger.");
			DefaultMercyOncePerGame = config.Bind<bool>("Session Defaults", "MercyOncePerGame", true, "Limit mercy vote to once per player per game.");
			FixPristineHealth = config.Bind<bool>("Session Defaults", "FixPristineHealth", true, "Stop Pristine Perseverance from collapsing HP when a later card reduces health.");
			EnableAutoPickCurses = config.Bind<bool>("Session Defaults", "EnableAutoPickCurses", true, "Register the auto-pick curse set (mutually exclusive with each other).");
			PanicTimerSeconds = config.Bind<float>("Session Defaults", "PanicTimerSeconds", 3f, "How long Panic Pick waits before choosing for you.");
			EnableThiefCard = config.Bind<bool>("Session Defaults", "EnableThief", true, "Allow the Thief legendary card in this session.");
			EnableTakebacksies = config.Bind<bool>("Session Defaults", "EnableTakebacksies", true, "Allow Takebacksies and inject it for stolen-from players.");
			EnableSandbagSimulator = config.Bind<bool>("Session Defaults", "EnableSandbagSimulator", true, "Allow the Sandbag Simulator legendary card in this session.");
			EnableJarOfDirt = config.Bind<bool>("Session Defaults", "EnableJarOfDirt", true, "Allow the Jar of Dirt unique card in this session.");
			SandbagOncePerGame = config.Bind<bool>("Session Defaults", "SandbagOncePerGame", true, "Limit Sandbag Simulator to once per game per player.");
			LogPickPhase = config.Bind<bool>("Diagnostics", "LogPickPhase", false, "Log a line each time a card pick starts. Only useful when reporting a bug.");
			if (!config.Bind<bool>("Take All", "Enabled", true, "Deprecated - use Session Defaults.TakeAllMode.").Value && DefaultTakeAllMode.Value != TakeAllMode.Disabled)
			{
				DefaultTakeAllMode.Value = TakeAllMode.Disabled;
			}
			EnableStatsHud = config.Bind<bool>("Stats HUD", "Enabled", true, "Always-on stats panel (replaces Infoholic).");
			StatsHudVisible = config.Bind<bool>("Stats HUD", "Visible", true, "Whether the HUD is currently shown (toggle in-game with StatsHudToggleKey).");
			StatsHudCollapsed = config.Bind<bool>("Stats HUD", "Collapsed", false, "Show the HUD as a minimal strip instead of the full panel.");
			StatsHudSimpleMode = config.Bind<bool>("Stats HUD", "SimpleMode", true, "Show a compact stat list instead of every stat.");
			StatsHudUltraCompact = config.Bind<bool>("Stats HUD", "UltraCompact", false, "Narrow HUD with fewer lines.");
			StatsHudPeekMode = config.Bind<bool>("Stats HUD", "PeekMode", false, "Only show the HUD while holding the peek key.");
			StatsHudPeekKey = config.Bind<KeyCode>("Stats HUD", "PeekKey", (KeyCode)308, "Hold to show HUD when PeekMode is enabled.");
			HideStatsHudDuringPick = config.Bind<bool>("Stats HUD", "HideDuringPick", false, "Hide the always-on HUD during card pick.");
			HideStatsHudDuringBattle = config.Bind<bool>("Stats HUD", "HideDuringBattle", false, "Hide the always-on HUD during battle rounds.");
			StatsHudToggleKey = config.Bind<KeyCode>("Stats HUD", "ToggleKey", (KeyCode)111, "Toggle the always-on HUD visibility.");
			StatsHudOpacity = config.Bind<float>("Stats HUD", "Opacity", 0f, "Background opacity for the HUD panel (0 = text only).");
			if (Mathf.Abs(StatsHudOpacity.Value - 0.78f) < 0.001f)
			{
				StatsHudOpacity.Value = 0f;
			}
			StatsHudFontScale = config.Bind<float>("Stats HUD", "FontScale", 1f, "Text scale multiplier (auto-scales with resolution too).");
			StatsHudColorR = config.Bind<float>("Stats HUD", "ColorR", 1f, "HUD text red channel.");
			StatsHudColorG = config.Bind<float>("Stats HUD", "ColorG", 1f, "HUD text green channel.");
			StatsHudColorB = config.Bind<float>("Stats HUD", "ColorB", 1f, "HUD text blue channel.");
			EnableStatsTab = config.Bind<bool>("Stats Tab", "Enabled", true, "Tab overlay for all players (replaces TabInfo). Press Tab in-game.");
			EnableTabCompare = config.Bind<bool>("Stats Tab", "EnableCompare", true, "Compare mode inside the Tab overlay (C toggles, [ ] switches opponent).");
			TabPanelWidth = config.Bind<float>("Stats Tab", "PanelWidth", 480f, "Tab overlay width in pixels (before scale).");
			TabPanelHeightFraction = config.Bind<float>("Stats Tab", "PanelHeightFraction", 0.82f, "Tab overlay height as a fraction of screen height.");
			TabPanelOpacity = config.Bind<float>("Stats Tab", "PanelOpacity", 0.94f, "Tab overlay background opacity.");
			TabAnchorLeft = config.Bind<bool>("Stats Tab", "AnchorLeft", false, "Deprecated - drag the Tab panel in-game.");
			TabPosX = config.Bind<float>("Stats Tab", "PosX", -1f, "Tab overlay X in canvas pixels. Negative = default centered.");
			TabPosY = config.Bind<float>("Stats Tab", "PosY", -1f, "Tab overlay Y in canvas pixels. Negative = default centered.");
			ShowPing = config.Bind<bool>("Stats Tab", "ShowPing", true, "Show Photon ping next to player names in the Tab overlay and HUD (online games).");
			ShowPickDeltasOnHud = config.Bind<bool>("Stats HUD", "ShowPickDeltas", true, "During picks, show card deltas on the bottom-left HUD for whoever is picking (hover a card to preview).");
			StatsPanelScale = config.Bind<float>("Stats Layout", "PanelScale", 1f, "Global UI scale multiplier.");
			StatsHudOffsetX = config.Bind<float>("Stats Layout", "HudOffsetX", 14f, "HUD distance from left edge.");
			StatsHudOffsetY = config.Bind<float>("Stats Layout", "HudOffsetY", 14f, "HUD distance from bottom edge.");
			StatsAccentR = config.Bind<float>("Stats Layout", "AccentR", 0.35f, "Accent color red.");
			StatsAccentG = config.Bind<float>("Stats Layout", "AccentG", 0.82f, "Accent color green.");
			StatsAccentB = config.Bind<float>("Stats Layout", "AccentB", 0.72f, "Accent color blue.");
			AutoCloseTabDuringPick = config.Bind<bool>("Stats Tab", "AutoCloseDuringPick", false, "Close the Tab overlay when a card pick starts so cards stay clickable. Tab still toggles it open again.");
		}
	}
	internal static class CurseOwnership
	{
		internal const float FumbleChance = 0.5f;

		internal const float KickbackDamageMultiplier = 1.25f;

		internal const float KickbackForce = 1700f;

		internal static bo