Decompiled source of RepentanceCards v1.0.0

RepentanceCards.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.Win32;
using ModdingUtils.Utils;
using Photon.Pun;
using RepentanceCards.Cards;
using RepentanceCards.Core;
using RepentanceCards.Effects;
using SimulationChamber;
using UnboundLib;
using UnboundLib.Cards;
using UnboundLib.GameModes;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace RepentanceCards
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.repentancecards.rounds.isaac", "Repentance Cards", "1.0.0")]
	[BepInProcess("Rounds.exe")]
	public class RepentancePlugin : BaseUnityPlugin
	{
		public const string ModId = "com.repentancecards.rounds.isaac";

		public const string ModName = "Repentance Cards";

		public const string Version = "1.0.0";

		public const string ModInitials = "ISAAC";

		internal static RepentancePlugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> UseIsaacSprites;

		internal static ConfigEntry<bool> AutoExtractIsaacSprites;

		internal static ConfigEntry<string> IsaacInstallPath;

		internal static ConfigEntry<bool> AnnounceTransformations;

		internal static ConfigEntry<bool> CharacterSelectEnabled;

		internal static ConfigEntry<bool> ShowCharacterHeads;

		internal static ConfigEntry<bool> DebugKeys;

		internal static ConfigEntry<float> ArtScale;

		internal static ConfigEntry<float> ArtOffsetY;

		private void Awake()
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			UseIsaacSprites = ((BaseUnityPlugin)this).Config.Bind<bool>("Art", "UseIsaacSprites", true, "Use the item sprites from your own copy of The Binding of Isaac (if installed) as card art. Nothing is copied into the mod itself.");
			AutoExtractIsaacSprites = ((BaseUnityPlugin)this).Config.Bind<bool>("Art", "AutoExtractIsaacSprites", true, "If Isaac is installed but its item sprites are still packed, run Isaac's own ResourceExtractor once (in the background) to unpack them.");
			IsaacInstallPath = ((BaseUnityPlugin)this).Config.Bind<string>("Art", "IsaacInstallPath", "", "Optional: full path to your 'The Binding of Isaac Rebirth' folder if it isn't found automatically.");
			CharacterSelectEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "CharacterSelect", true, "The first pick of each game is a choice of Isaac characters. Everyone in the lobby should use the same setting.");
			ShowCharacterHeads = ((BaseUnityPlugin)this).Config.Bind<bool>("Art", "ShowCharacterHeads", true, "Show your Isaac character's head on your player (needs The Binding of Isaac installed on this PC).");
			DebugKeys = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "TestKeys", false, "Offline test hotkeys: F5 give character, F6 give item, F7 shoot, F8 block, F9 log cards, F10 battle refresh, F11 reload config.");
			ArtScale = ((BaseUnityPlugin)this).Config.Bind<float>("Art", "ArtSize", 0.64f, "Size of the item art relative to the card's art window.");
			ArtOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Art", "ArtOffsetY", 0f, "Moves the item art up (+) or down (-), as a fraction of the art window's height.");
			AnnounceTransformations = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "AnnounceTransformations", true, "Show a big on-screen banner when someone completes a transformation.");
			Harmony val = new Harmony("com.repentancecards.rounds.isaac");
			Type[] types = typeof(RepentancePlugin).Assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0)
				{
					try
					{
						val.CreateClassProcessor(type).Patch();
					}
					catch (Exception ex)
					{
						Log.LogError((object)("Harmony patch " + type.Name + " failed: " + ex.Message));
					}
				}
			}
		}

		private void Start()
		{
			try
			{
				ArtManager.Init();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Art init failed: " + ex));
			}
			CardRegistry.RegisterAll();
			try
			{
				CharacterSelect.Register();
			}
			catch (Exception ex2)
			{
				Log.LogError((object)("Character select registration failed: " + ex2));
			}
			GameModeManager.AddHook("GameStart", (Func<IGameModeHandler, IEnumerator>)OnGameStart);
			GameModeManager.AddHook("BattleStart", (Func<IGameModeHandler, IEnumerator>)OnBattleStart);
			GameModeManager.AddHook("PointEnd", (Func<IGameModeHandler, IEnumerator>)OnPointEnd);
			GameModeManager.AddHook("PickEnd", (Func<IGameModeHandler, IEnumerator>)OnPickEnd);
			ExtensionMethods.ExecuteAfterSeconds((MonoBehaviour)(object)this, 3f, (Action)delegate
			{
				try
				{
					VanillaEffects.LogVanillaCards();
				}
				catch (Exception ex3)
				{
					Log.LogWarning((object)ex3.ToString());
				}
			});
		}

		private void Update()
		{
			try
			{
				ArtManager.Tick();
			}
			catch (Exception ex)
			{
				Log.LogError((object)ex.ToString());
			}
			DebugTools.Tick();
		}

		private IEnumerator OnGameStart(IGameModeHandler gm)
		{
			try
			{
				VanillaEffects.ResolvePending();
				IsaacPlayerState.ResetAllForNewGame();
				CharacterSelect.Active = CharacterSelectEnabled.Value;
			}
			catch (Exception ex)
			{
				Log.LogError((object)ex.ToString());
			}
			yield break;
		}

		private IEnumerator OnBattleStart(IGameModeHandler gm)
		{
			CharacterSelect.Active = false;
			try
			{
				IsaacPlayerState.OnBattleStartAll();
			}
			catch (Exception ex)
			{
				Log.LogError((object)ex.ToString());
			}
			yield break;
		}

		private IEnumerator OnPointEnd(IGameModeHandler gm)
		{
			try
			{
				IsaacPlayerState.OnPointEndAll();
			}
			catch (Exception ex)
			{
				Log.LogError((object)ex.ToString());
			}
			yield break;
		}

		private IEnumerator OnPickEnd(IGameModeHandler gm)
		{
			CharacterSelect.Active = false;
			bool flag = false;
			try
			{
				flag = Transformations.CheckAllPlayers();
			}
			catch (Exception ex)
			{
				Log.LogError((object)ex.ToString());
			}
			if (flag)
			{
				yield return (object)new WaitForSecondsRealtime(0.75f);
			}
		}
	}
}
namespace RepentanceCards.Patches
{
	[HarmonyPatch(typeof(HealthHandler), "TakeDamage", new Type[]
	{
		typeof(Vector2),
		typeof(Vector2),
		typeof(Color),
		typeof(GameObject),
		typeof(Player),
		typeof(bool),
		typeof(bool)
	})]
	internal class HolyMantlePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(HealthHandler __instance, Vector2 damage)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (damage == Vector2.zero || ((Vector2)(ref damage)).magnitude < 0.5f)
				{
					return true;
				}
				IsaacPlayerState component = ((Component)__instance).GetComponent<IsaacPlayerState>();
				if ((Object)(object)component == (Object)null || component.MantleCharges <= 0)
				{
					return true;
				}
				CharacterData data = component.data;
				if ((Object)(object)data == (Object)null || !data.isPlaying || data.dead)
				{
					return true;
				}
				component.MantleCharges--;
				component.OnMantleBroken();
				return false;
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogWarning((object)("Holy Mantle: " + ex.Message));
				return true;
			}
		}
	}
}
namespace RepentanceCards.Effects
{
	internal static class VisualUtil
	{
		private static Sprite ring;

		private static Sprite softCircle;

		public static Sprite Ring
		{
			get
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Expected O, but got Unknown
				//IL_00f8: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)ring != (Object)null)
				{
					return ring;
				}
				Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false);
				float num = 63.5f;
				for (int i = 0; i < 128; i++)
				{
					for (int j = 0; j < 128; j++)
					{
						float num2 = Mathf.Sqrt(((float)j - num) * ((float)j - num) + ((float)i - num) * ((float)i - num)) / num;
						float num3 = Mathf.Clamp01(1f - Mathf.Abs(num2 - 0.9f) / 0.08f);
						float num4 = Mathf.Clamp01(1f - num2) * 0.18f;
						val.SetPixel(j, i, new Color(1f, 1f, 1f, Mathf.Max(num3, (num2 < 1f) ? num4 : 0f)));
					}
				}
				val.Apply();
				ring = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 64f);
				return ring;
			}
		}

		public static Sprite SoftCircle
		{
			get
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Expected O, but got Unknown
				//IL_00a6: 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_006f: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)softCircle != (Object)null)
				{
					return softCircle;
				}
				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 = Mathf.Sqrt(((float)j - num) * ((float)j - num) + ((float)i - num) * ((float)i - num)) / num;
						float num3 = Mathf.Clamp01(1f - num2);
						val.SetPixel(j, i, new Color(1f, 1f, 1f, num3 * num3));
					}
				}
				val.Apply();
				softCircle = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 32f);
				return softCircle;
			}
		}

		public static void CopySorting(SpriteRenderer target, GameObject source, int orderOffset)
		{
			SpriteRenderer[] componentsInChildren = source.GetComponentsInChildren<SpriteRenderer>(true);
			if (componentsInChildren.Length == 0)
			{
				((Renderer)target).sortingOrder = 100;
				return;
			}
			SpriteRenderer val = componentsInChildren.OrderByDescending((SpriteRenderer r) => ((Renderer)r).sortingOrder).First();
			((Renderer)target).sortingLayerID = ((Renderer)val).sortingLayerID;
			((Renderer)target).sortingOrder = ((Renderer)val).sortingOrder + orderOffset;
		}
	}
	public class MantleVisual : MonoBehaviour
	{
		private SpriteRenderer sr;

		private bool visible;

		private bool breaking;

		public static MantleVisual Create(IsaacPlayerState owner)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0023: 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_003d: 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)
			GameObject val = new GameObject("HolyMantleBubble");
			val.transform.SetParent(((Component)owner).transform, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localScale = Vector3.one * 1.35f;
			MantleVisual mantleVisual = val.AddComponent<MantleVisual>();
			mantleVisual.sr = val.AddComponent<SpriteRenderer>();
			mantleVisual.sr.sprite = VisualUtil.Ring;
			mantleVisual.sr.color = new Color(0.85f, 0.95f, 1f, 0.75f);
			VisualUtil.CopySorting(mantleVisual.sr, ((Component)owner).gameObject, 5);
			return mantleVisual;
		}

		public void SetVisible(bool v)
		{
			visible = v;
			if (!breaking && (Object)(object)sr != (Object)null)
			{
				((Renderer)sr).enabled = v;
			}
		}

		private void Update()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (!breaking && !((Object)(object)sr == (Object)null) && visible)
			{
				float num = 0.65f + 0.15f * Mathf.Sin(Time.time * 4f);
				sr.color = new Color(0.85f, 0.95f, 1f, num);
			}
		}

		public void Break()
		{
			if (((Component)this).gameObject.activeInHierarchy)
			{
				((MonoBehaviour)this).StartCoroutine(BreakRoutine());
			}
		}

		private IEnumerator BreakRoutine()
		{
			breaking = true;
			((Renderer)sr).enabled = true;
			float t = 0f;
			Vector3 start = ((Component)this).transform.localScale;
			while (t < 0.35f)
			{
				t += Time.deltaTime;
				float num = t / 0.35f;
				((Component)this).transform.localScale = start * (1f + num * 0.8f);
				sr.color = new Color(1f, 1f, 1f, 1f - num);
				yield return null;
			}
			((Component)this).transform.localScale = start;
			breaking = false;
			((Renderer)sr).enabled = visible;
		}
	}
	public class FamiliarVisual : MonoBehaviour
	{
		private IsaacPlayerState owner;

		private SpriteRenderer sr;

		private Vector3 velocity;

		public bool Enabled = true;

		public static FamiliarVisual Create(IsaacPlayerState owner, Sprite sprite)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//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_0042: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("IsaacFamiliar");
			FamiliarVisual familiarVisual = val.AddComponent<FamiliarVisual>();
			familiarVisual.owner = owner;
			familiarVisual.sr = val.AddComponent<SpriteRenderer>();
			familiarVisual.sr.sprite = sprite;
			if ((Object)(object)sprite != (Object)null)
			{
				Bounds bounds = sprite.bounds;
				float y = ((Bounds)(ref bounds)).size.y;
				val.transform.localScale = Vector3.one * ((y > 0.001f) ? (1.1f / y) : 1f);
			}
			VisualUtil.CopySorting(familiarVisual.sr, ((Component)owner).gameObject, 4);
			familiarVisual.SnapToOwner();
			return familiarVisual;
		}

		private Vector3 Target()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)owner).transform.position + new Vector3(-1.3f, 1.1f + Mathf.Sin(Time.time * 3f) * 0.15f, 0f);
		}

		public void SnapToOwner()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)owner != (Object)null)
			{
				((Component)this).transform.position = Target();
			}
		}

		private void LateUpdate()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)owner == (Object)null)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			CharacterData data = owner.data;
			bool flag = Enabled && (Object)(object)data != (Object)null && data.isPlaying && !data.dead && ((Component)owner).gameObject.activeInHierarchy;
			if (((Renderer)sr).enabled != flag)
			{
				((Renderer)sr).enabled = flag;
				if (flag)
				{
					SnapToOwner();
				}
			}
			if (flag)
			{
				((Component)this).transform.position = Vector3.SmoothDamp(((Component)this).transform.position, Target(), ref velocity, 0.12f);
			}
		}
	}
	public class GodheadAura : MonoBehaviour
	{
		public Player owner;

		public int stacks = 1;

		private float timer;

		private const float Radius = 2.2f;

		private const float TickSeconds = 0.25f;

		private const float DamagePerTick = 5f;

		private void Start()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GameObject val = new GameObject("GodheadGlow");
				val.transform.SetParent(((Component)this).transform, false);
				val.transform.localPosition = Vector3.zero;
				float num = 2.2f * (1f + 0.25f * (float)(stacks - 1));
				Vector3 lossyScale = ((Component)this).transform.lossyScale;
				float num2 = ((Mathf.Abs(lossyScale.x) > 0.0001f) ? (num / lossyScale.x) : num);
				val.transform.localScale = Vector3.one * num2;
				SpriteRenderer obj = val.AddComponent<SpriteRenderer>();
				obj.sprite = VisualUtil.SoftCircle;
				obj.color = new Color(1f, 0.95f, 0.6f, 0.35f);
				((Renderer)obj).sortingOrder = 50;
			}
			catch
			{
			}
		}

		private void Update()
		{
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			timer -= TimeHandler.deltaTime;
			if (timer > 0f)
			{
				return;
			}
			timer = 0.25f;
			if ((Object)(object)owner == (Object)null || (Object)(object)owner.data == (Object)null || (Object)(object)owner.data.view == (Object)null || (!owner.data.view.IsMine && !PhotonNetwork.OfflineMode) || (Object)(object)PlayerManager.instance == (Object)null)
			{
				return;
			}
			float num = 2.2f * (1f + 0.25f * (float)(stacks - 1));
			foreach (Player player in PlayerManager.instance.players)
			{
				if (EnemyUtil.IsAliveEnemy(owner, player))
				{
					Vector2 val = Vector2.op_Implicit(((Component)player).transform.position - ((Component)this).transform.position);
					if (!(((Vector2)(ref val)).magnitude > num) && (!((Object)(object)player.data.block != (Object)null) || !player.data.block.IsBlocking()))
					{
						Vector2 val2 = ((((Vector2)(ref val)).sqrMagnitude > 0.0001f) ? ((Vector2)(ref val)).normalized : Vector2.up);
						((Damagable)player.data.healthHandler).CallTakeDamage(val2 * 5f * (float)stacks, Vector2.op_Implicit(((Component)this).transform.position), (GameObject)null, owner, true);
					}
				}
			}
		}
	}
	public class CharacterHeadVisual : MonoBehaviour
	{
		private SpriteRenderer sr;

		private CharacterData data;

		public string Key;

		public static CharacterHeadVisual Create(IsaacPlayerState owner, Sprite head, string key)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			GameObject val = new GameObject("IsaacCharacterHead");
			val.transform.SetParent(((Component)owner).transform, false);
			CharacterHeadVisual characterHeadVisual = val.AddComponent<CharacterHeadVisual>();
			characterHeadVisual.data = owner.data;
			characterHeadVisual.sr = val.AddComponent<SpriteRenderer>();
			characterHeadVisual.sr.sprite = head;
			characterHeadVisual.Key = key;
			VisualUtil.CopySorting(characterHeadVisual.sr, ((Component)owner).gameObject, 8);
			return characterHeadVisual;
		}

		public void Set(Sprite head, string key)
		{
			sr.sprite = head;
			Key = key;
		}

		private void LateUpdate()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sr == (Object)null || (Object)(object)sr.sprite == (Object)null || (Object)(object)data == (Object)null)
			{
				return;
			}
			float num = 1.2f;
			Bounds bounds;
			try
			{
				if ((Object)(object)data.mainCol != (Object)null)
				{
					bounds = data.mainCol.bounds;
					num = ((Bounds)(ref bounds)).size.x;
				}
			}
			catch
			{
			}
			bounds = sr.sprite.bounds;
			float x = ((Bounds)(ref bounds)).size.x;
			Vector3 val = (((Object)(object)((Component)this).transform.parent != (Object)null) ? ((Component)this).transform.parent.lossyScale : Vector3.one);
			float num2 = num * 1.45f;
			float num3 = ((x > 0.0001f && Mathf.Abs(val.x) > 0.0001f) ? (num2 / (x * val.x)) : 1f);
			((Component)this).transform.localScale = new Vector3(num3, num3, 1f);
			((Component)this).transform.localPosition = Vector3.zero;
			((Component)this).transform.rotation = Quaternion.identity;
			if ((Object)(object)data.input != (Object)null && Mathf.Abs(data.input.aimDirection.x) > 0.1f)
			{
				sr.flipX = data.input.aimDirection.x < 0f;
			}
		}
	}
}
namespace RepentanceCards.Core
{
	internal static class ArtManager
	{
		private class Entry
		{
			public int IsaacId;

			public int TrinketId;

			public string GfxPath;

			public string Fallback;

			public Image Image;
		}

		private static GameObject templateRoot;

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

		private static readonly Dictionary<string, Entry> entries = new Dictionary<string, Entry>();

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

		private static List<string> spriteRoots = new List<string>();

		private static string isaacDir;

		private static bool initialized;

		public static bool IsaacSpritesAvailable => IsaacLocator.HasItemSprites(spriteRoots);

		public static event Action SpritesRefreshed;

		public static void Init()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (initialized)
			{
				return;
			}
			initialized = true;
			templateRoot = new GameObject("RepentanceCards_ArtTemplates");
			templateRoot.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)templateRoot);
			LoadFallbacks();
			if (!RepentancePlugin.UseIsaacSprites.Value)
			{
				RepentancePlugin.Log.LogInfo((object)"Isaac sprites disabled in config; using bundled icons.");
				return;
			}
			isaacDir = IsaacLocator.FindIsaacDir();
			if (isaacDir == null)
			{
				RepentancePlugin.Log.LogInfo((object)"The Binding of Isaac was not found on this PC; using bundled icons.");
				return;
			}
			RepentancePlugin.Log.LogInfo((object)("Found The Binding of Isaac at: " + isaacDir));
			spriteRoots = IsaacLocator.FindGfxRoots(isaacDir);
			bool flag = IsaacLocator.HasItemSprites(spriteRoots);
			bool flag2 = IsaacLocator.FindGfxFile(spriteRoots, "ui/stage/playerportrait_isaac.png") != null && IsaacLocator.FindGfxFile(spriteRoots, "characters/costumes/character_001_isaac.png") != null;
			if (flag)
			{
				RepentancePlugin.Log.LogInfo((object)("Using Isaac sprites from: " + string.Join(" | ", spriteRoots.ToArray())));
			}
			if (!(flag && flag2))
			{
				if (RepentancePlugin.AutoExtractIsaacSprites.Value && SpriteExtractor.CanExtract(isaacDir))
				{
					RepentancePlugin.Log.LogInfo((object)"Some Isaac sprites are still packed; running Isaac's ResourceExtractor in the background...");
					SpriteExtractor.StartInBackground(isaacDir);
				}
				else if (!flag)
				{
					RepentancePlugin.Log.LogInfo((object)"Isaac's sprites are packed and auto-extract is off/unavailable; using bundled icons.");
				}
			}
		}

		public static void Tick()
		{
			if (SpriteExtractor.Finished)
			{
				SpriteExtractor.Finished = false;
				if (SpriteExtractor.Succeeded)
				{
					spriteRoots = IsaacLocator.FindGfxRoots(isaacDir);
					RepentancePlugin.Log.LogInfo((object)("Isaac ResourceExtractor finished: " + SpriteExtractor.Message));
					RefreshAll();
				}
				else
				{
					RepentancePlugin.Log.LogWarning((object)("Isaac ResourceExtractor did not produce sprites: " + SpriteExtractor.Message));
				}
			}
		}

		private static void LoadFallbacks()
		{
			Assembly assembly = typeof(ArtManager).Assembly;
			string[] manifestResourceNames = assembly.GetManifestResourceNames();
			foreach (string text in manifestResourceNames)
			{
				if (!text.StartsWith("RepentanceCards.Resources.") || !text.EndsWith(".png"))
				{
					continue;
				}
				string key = text.Substring("RepentanceCards.Resources.".Length, text.Length - "RepentanceCards.Resources.".Length - 4);
				using Stream stream = assembly.GetManifestResourceStream(text);
				if (stream == null)
				{
					continue;
				}
				byte[] array = new byte[stream.Length];
				int num;
				for (int j = 0; j < array.Length; j += num)
				{
					num = stream.Read(array, j, array.Length - j);
					if (num <= 0)
					{
						break;
					}
				}
				Sprite val = MakeSprite(array, (FilterMode)0);
				if ((Object)(object)val != (Object)null)
				{
					fallbackSprites[key] = val;
				}
			}
			RepentancePlugin.Log.LogInfo((object)$"Loaded {fallbackSprites.Count} bundled icons.");
		}

		private static Sprite MakeSprite(byte[] bytes, FilterMode filter)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, bytes))
			{
				return null;
			}
			((Texture)val).filterMode = filter;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			return Sprite.Create(val, TrimRect(val), new Vector2(0.5f, 0.5f), 100f);
		}

		private static Rect TrimRect(Texture2D tex)
		{
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Color32[] pixels = tex.GetPixels32();
				int width = ((Texture)tex).width;
				int height = ((Texture)tex).height;
				int num = width;
				int num2 = height;
				int num3 = -1;
				int num4 = -1;
				for (int i = 0; i < height; i++)
				{
					for (int j = 0; j < width; j++)
					{
						if (pixels[i * width + j].a >= 8)
						{
							if (j < num)
							{
								num = j;
							}
							if (j > num3)
							{
								num3 = j;
							}
							if (i < num2)
							{
								num2 = i;
							}
							if (i > num4)
							{
								num4 = i;
							}
						}
					}
				}
				if (num3 < 0)
				{
					return new Rect(0f, 0f, (float)width, (float)height);
				}
				num = Mathf.Max(0, num - 1);
				num2 = Mathf.Max(0, num2 - 1);
				num3 = Mathf.Min(width - 1, num3 + 1);
				num4 = Mathf.Min(height - 1, num4 + 1);
				return new Rect((float)num, (float)num2, (float)(num3 - num + 1), (float)(num4 - num2 + 1));
			}
			catch
			{
				return new Rect(0f, 0f, (float)((Texture)tex).width, (float)((Texture)tex).height);
			}
		}

		private static Sprite LoadIsaacSprite(int id, int trinketId)
		{
			if (spriteRoots.Count == 0)
			{
				return null;
			}
			string text = ((trinketId > 0) ? ("t" + trinketId) : ("c" + id));
			if (isaacSpriteCache.TryGetValue(text, out var value))
			{
				return value;
			}
			Sprite val = null;
			try
			{
				string text2 = ((trinketId > 0) ? IsaacLocator.FindTrinket(spriteRoots, trinketId) : IsaacLocator.FindCollectible(spriteRoots, id));
				if (text2 != null)
				{
					val = MakeSprite(File.ReadAllBytes(text2), (FilterMode)0);
				}
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogWarning((object)("Could not load Isaac sprite " + text + ": " + ex.Message));
			}
			isaacSpriteCache[text] = val;
			return val;
		}

		private static Texture2D LoadGfxTexture(string relative)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			if (spriteRoots.Count == 0 || string.IsNullOrEmpty(relative))
			{
				return null;
			}
			try
			{
				string text = IsaacLocator.FindGfxFile(spriteRoots, relative);
				if (text == null)
				{
					return null;
				}
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(val, File.ReadAllBytes(text)))
				{
					return null;
				}
				((Texture)val).filterMode = (FilterMode)0;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				return val;
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogWarning((object)("Could not load Isaac file " + relative + ": " + ex.Message));
				return null;
			}
		}

		public static Sprite LoadGfxSprite(string relative)
		{
			//IL_003c: 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)
			if (string.IsNullOrEmpty(relative))
			{
				return null;
			}
			string key = "g:" + relative;
			if (isaacSpriteCache.TryGetValue(key, out var value))
			{
				return value;
			}
			Texture2D val = LoadGfxTexture(relative);
			Sprite val2 = (((Object)(object)val != (Object)null) ? Sprite.Create(val, TrimRect(val), new Vector2(0.5f, 0.5f), 100f) : null);
			isaacSpriteCache[key] = val2;
			return val2;
		}

		public static Sprite BuildCharacterHead(string skinFile, string costumeFile)
		{
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Expected O, but got Unknown
			//IL_0102: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(skinFile))
			{
				return null;
			}
			string key = "h:" + skinFile + "|" + costumeFile;
			if (isaacSpriteCache.TryGetValue(key, out var value))
			{
				return value;
			}
			Sprite val = null;
			try
			{
				Texture2D val2 = LoadGfxTexture("characters/costumes/" + skinFile);
				if ((Object)(object)val2 != (Object)null && ((Texture)val2).width >= 32 && ((Texture)val2).height >= 32)
				{
					Color[] pixels = val2.GetPixels(0, ((Texture)val2).height - 32, 32, 32);
					if (!string.IsNullOrEmpty(costumeFile))
					{
						Texture2D val3 = LoadGfxTexture("characters/costumes/" + costumeFile);
						if ((Object)(object)val3 != (Object)null && ((Texture)val3).width >= 32 && ((Texture)val3).height >= 32)
						{
							Color[] pixels2 = val3.GetPixels(0, ((Texture)val3).height - 32, 32, 32);
							for (int i = 0; i < pixels.Length; i++)
							{
								float a = pixels2[i].a;
								if (!(a <= 0f))
								{
									Color val4 = pixels[i];
									pixels[i] = new Color(pixels2[i].r * a + val4.r * (1f - a), pixels2[i].g * a + val4.g * (1f - a), pixels2[i].b * a + val4.b * (1f - a), a + val4.a * (1f - a));
								}
							}
						}
					}
					Texture2D val5 = new Texture2D(32, 32, (TextureFormat)4, false);
					val5.SetPixels(pixels);
					((Texture)val5).filterMode = (FilterMode)0;
					((Texture)val5).wrapMode = (TextureWrapMode)1;
					val5.Apply();
					val = Sprite.Create(val5, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.45f), 32f);
				}
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogWarning((object)("Could not build character head " + skinFile + ": " + ex.Message));
			}
			isaacSpriteCache[key] = val;
			return val;
		}

		private static Sprite Resolve(Entry e)
		{
			Sprite value = null;
			if (!string.IsNullOrEmpty(e.GfxPath))
			{
				value = LoadGfxSprite(e.GfxPath);
			}
			if ((Object)(object)value == (Object)null && (e.IsaacId > 0 || e.TrinketId > 0))
			{
				value = LoadIsaacSprite(e.IsaacId, e.TrinketId);
			}
			if ((Object)(object)value == (Object)null && e.Fallback != null)
			{
				fallbackSprites.TryGetValue(e.Fallback, out value);
			}
			if ((Object)(object)value == (Object)null)
			{
				fallbackSprites.TryGetValue("generic", out value);
			}
			return value;
		}

		public static Sprite GetSprite(int isaacId, string fallback)
		{
			return Resolve(new Entry
			{
				IsaacId = isaacId,
				Fallback = fallback
			});
		}

		public static GameObject GetArtTemplate(IsaacCard card)
		{
			//IL_0035: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			if ((Object)(object)templateRoot == (Object)null)
			{
				Init();
			}
			GameObject val = new GameObject("IsaacArt_" + card.Title, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(templateRoot.transform, false);
			Image val2 = val.AddComponent<Image>();
			val2.preserveAspect = true;
			((Graphic)val2).raycastTarget = false;
			val.AddComponent<CardArtFitter>();
			Entry entry = new Entry
			{
				IsaacId = card.IsaacId,
				TrinketId = card.IsaacTrinketId,
				GfxPath = card.IsaacArtPath,
				Fallback = card.FallbackArt,
				Image = val2
			};
			val2.sprite = Resolve(entry);
			entries[card.Title] = entry;
			return val;
		}

		private static void RefreshAll()
		{
			isaacSpriteCache.Clear();
			try
			{
				ArtManager.SpritesRefreshed?.Invoke();
			}
			catch
			{
			}
			foreach (Entry value in entries.Values)
			{
				if ((Object)(object)value.Image != (Object)null)
				{
					value.Image.sprite = Resolve(value);
				}
			}
		}
	}
	internal class CardArtFitter : MonoBehaviour
	{
		private static bool loggedLayout;

		private void Start()
		{
			Apply();
		}

		private void LateUpdate()
		{
			Apply();
		}

		private void Apply()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				RectTransform val = (RectTransform)((Component)this).transform;
				Transform parent = ((Component)this).transform.parent;
				RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
				if (!loggedLayout && (Object)(object)val2 != (Object)null)
				{
					loggedLayout = true;
					ManualLogSource log = RepentancePlugin.Log;
					object[] obj = new object[6]
					{
						((Object)val2).name,
						val2.rect,
						val2.pivot,
						val2.anchoredPosition,
						((Transform)val2).localScale,
						null
					};
					Transform parent2 = ((Transform)val2).parent;
					obj[5] = ((parent2 != null) ? ((Object)parent2).name : null);
					log.LogInfo((object)string.Format("Card layout: art parent '{0}' rect={1} pivot={2} anchoredPos={3} localScale={4}; grandparent '{5}'", obj));
				}
				float num = ((RepentancePlugin.ArtScale != null) ? RepentancePlugin.ArtScale.Value : 0.64f);
				float num2 = ((RepentancePlugin.ArtOffsetY != null) ? RepentancePlugin.ArtOffsetY.Value : 0f);
				val.anchorMin = new Vector2(0.5f, 0.5f);
				val.anchorMax = new Vector2(0.5f, 0.5f);
				val.pivot = new Vector2(0.5f, 0.5f);
				((Transform)val).localScale = Vector3.one;
				((Transform)val).localRotation = Quaternion.identity;
				float num3;
				Rect rect;
				if (!((Object)(object)val2 != (Object)null))
				{
					num3 = 0f;
				}
				else
				{
					rect = val2.rect;
					num3 = ((Rect)(ref rect)).width;
				}
				float num4 = num3;
				float num5;
				if (!((Object)(object)val2 != (Object)null))
				{
					num5 = 0f;
				}
				else
				{
					rect = val2.rect;
					num5 = ((Rect)(ref rect)).height;
				}
				float num6 = num5;
				if (num4 > 1f && num6 > 1f)
				{
					float num7 = Mathf.Min(num4, num6) * num;
					val.sizeDelta = new Vector2(num7, num7);
					val.anchoredPosition = new Vector2(0f, num6 * num2);
				}
				else
				{
					val.sizeDelta = new Vector2(500f, 500f);
					val.anchoredPosition = Vector2.zero;
				}
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogWarning((object)("Art layout failed: " + ex.Message));
				((Behaviour)this).enabled = false;
			}
		}
	}
	public static class CardNames
	{
		public const string Pentagram = "Pentagram";

		public const string TheMark = "The Mark";

		public const string Abaddon = "Abaddon";

		public const string LordOfThePit = "Lord of the Pit";

		public const string SpiritOfTheNight = "Spirit of the Night";

		public const string WhoreOfBabylon = "Whore of Babylon";

		public const string BookOfBelial = "The Book of Belial";

		public const string CeremonialRobes = "Ceremonial Robes";

		public const string TheHalo = "The Halo";

		public const string HolyGrail = "Holy Grail";

		public const string DeadDove = "Dead Dove";

		public const string Rosary = "Rosary";

		public const string HolyLight = "Holy Light";

		public const string HolyMantle = "Holy Mantle";

		public const string SacredHeart = "Sacred Heart";

		public const string Godhead = "Godhead";

		public const string SpoonBender = "Spoon Bender";

		public const string RubberCement = "Rubber Cement";

		public const string OuijaBoard = "Ouija Board";

		public const string WiggleWorm = "Wiggle Worm";

		public const string LumpOfCoal = "A Lump of Coal";

		public const string Proptosis = "Proptosis";

		public const string Ipecac = "Ipecac";

		public const string Technology = "Technology";

		public const string MutantSpider = "Mutant Spider";

		public const string TwentyTwenty = "20/20";

		public const string SpiderBite = "Spider Bite";

		public const string CommonCold = "The Common Cold";

		public const string CricketsHead = "Cricket's Head";

		public const string WireCoatHanger = "Wire Coat Hanger";

		public const string TammysHead = "Tammy's Head";

		public const string YumHeart = "Yum Heart";

		public const string NineVolt = "9 Volt";

		public const string BloodyLust = "Bloody Lust";

		public const string BrotherBobby = "Brother Bobby";

		public const string CharmOfTheVampire = "Charm of the Vampire";

		public const string RoidRage = "Roid Rage";

		public const string Synthoil = "Synthoil";

		public const string ExperimentalTreatment = "Experimental Treatment";

		public const string Adrenaline = "Adrenaline";

		public const string Euthanasia = "Euthanasia";

		public const string GuppysHead = "Guppy's Head";

		public const string GuppysPaw = "Guppy's Paw";

		public const string GuppysTail = "Guppy's Tail";

		public const string GuppysHairball = "Guppy's Hairball";

		public const string GuppysCollar = "Guppy's Collar";

		public const string OddMushroomThin = "Odd Mushroom (Thin)";

		public const string OddMushroomLarge = "Odd Mushroom (Large)";

		public const string OneUp = "1up!";

		public const string BlueCap = "Blue Cap";

		public const string BOR_DeadCat = "Dead Cat";

		public const string BOR_ThePact = "The Pact";

		public const string BOR_Brimstone = "Brimstone";

		public const string BOR_GrowthHormones = "Growth Hormones";

		public const string BOR_SpeedBall = "Speed Ball";

		public const string BOR_MiniMush = "Mini Mush";

		public const string BOR_MagicMushroom = "Magic Mushroom";

		public const string TransformGuppy = "Guppy";

		public const string TransformSeraphim = "Seraphim";

		public const string TransformLeviathan = "Leviathan";

		public const string TransformSpun = "Spun";

		public const string TransformFunGuy = "Fun Guy";
	}
	internal static class CardRegistry
	{
		private static readonly Dictionary<string, CardInfo> byTitle = new Dictionary<string, CardInfo>(StringComparer.OrdinalIgnoreCase);

		private static readonly List<CardInfo> items = new List<CardInfo>();

		private static readonly List<CardInfo> characters = new List<CardInfo>();

		public static IEnumerable<CardInfo> Characters => characters.Where((CardInfo c) => (Object)(object)c != (Object)null);

		public static IEnumerable<CardInfo> Items => items.Where((CardInfo c) => (Object)(object)c != (Object)null);

		public static CardInfo Get(string title)
		{
			if (!byTitle.TryGetValue(title, out var value))
			{
				return null;
			}
			return value;
		}

		private static void Remember(CardInfo card, bool isItem)
		{
			if (!((Object)(object)card == (Object)null))
			{
				byTitle[card.cardName] = card;
				if (isItem)
				{
					items.Add(card);
				}
				if ((Object)(object)((Component)card).GetComponent<CharacterCard>() != (Object)null)
				{
					characters.Add(card);
				}
			}
		}

		private static void Build<T>() where T : IsaacCard
		{
			bool isItem = !typeof(CharacterCard).IsAssignableFrom(typeof(T)) && !typeof(TransformationCard).IsAssignableFrom(typeof(T));
			try
			{
				CustomCard.BuildCard<T>((Action<CardInfo>)delegate(CardInfo card)
				{
					Remember(card, isItem);
				});
			}
			catch (Exception arg)
			{
				RepentancePlugin.Log.LogError((object)$"Failed to build {typeof(T).Name}: {arg}");
			}
		}

		private static void BuildHidden<T>(IsaacSet set) where T : TransformationCard
		{
			try
			{
				CustomCard.BuildCard<T>((Action<CardInfo>)delegate(CardInfo card)
				{
					Remember(card, isItem: false);
					Transformations.RegisterHiddenCard(set, card);
				});
			}
			catch (Exception arg)
			{
				RepentancePlugin.Log.LogError((object)$"Failed to build {typeof(T).Name}: {arg}");
			}
		}

		public static void RegisterAll()
		{
			Build<Pentagram>();
			Build<TheMark>();
			Build<Abaddon>();
			Build<LordOfThePit>();
			Build<SpiritOfTheNight>();
			Build<WhoreOfBabylon>();
			Build<BookOfBelial>();
			Build<CeremonialRobes>();
			Build<TheHalo>();
			Build<HolyGrail>();
			Build<DeadDove>();
			Build<Rosary>();
			Build<HolyLight>();
			Build<HolyMantle>();
			Build<SacredHeart>();
			Build<Godhead>();
			Build<SpoonBender>();
			Build<RubberCement>();
			Build<OuijaBoard>();
			Build<WiggleWorm>();
			Build<LumpOfCoal>();
			Build<Proptosis>();
			Build<Ipecac>();
			Build<Technology>();
			Build<MutantSpider>();
			Build<TwentyTwenty>();
			Build<SpiderBite>();
			Build<TheCommonCold>();
			Build<CricketsHead>();
			Build<WireCoatHanger>();
			Build<TammysHead>();
			Build<YumHeart>();
			Build<NineVolt>();
			Build<BloodyLust>();
			Build<BrotherBobby>();
			Build<CharmOfTheVampire>();
			Build<RoidRage>();
			Build<Synthoil>();
			Build<ExperimentalTreatment>();
			Build<Adrenaline>();
			Build<Euthanasia>();
			Build<GuppysHead>();
			Build<GuppysPaw>();
			Build<GuppysTail>();
			Build<GuppysHairball>();
			Build<GuppysCollar>();
			Build<OddMushroomThin>();
			Build<OddMushroomLarge>();
			Build<OneUp>();
			Build<BlueCap>();
			Build<IsaacCharacter>();
			Build<MagdaleneCharacter>();
			Build<CainCharacter>();
			Build<JudasCharacter>();
			Build<BlueBabyCharacter>();
			Build<EveCharacter>();
			Build<SamsonCharacter>();
			Build<AzazelCharacter>();
			Build<LazarusCharacter>();
			Build<EdenCharacter>();
			Build<TheLostCharacter>();
			Build<LilithCharacter>();
			Build<KeeperCharacter>();
			BuildHidden<GuppyTransformation>(IsaacSet.Guppy);
			BuildHidden<SeraphimTransformation>(IsaacSet.Seraphim);
			BuildHidden<LeviathanTransformation>(IsaacSet.Leviathan);
			BuildHidden<SpunTransformation>(IsaacSet.Spun);
			BuildHidden<FunGuyTransformation>(IsaacSet.FunGuy);
		}
	}
	internal static class CharacterSelect
	{
		public static bool Active;

		private static bool registered;

		public static void Register()
		{
			if (!registered)
			{
				registered = true;
				Cards.instance.AddCardValidationFunction((Func<Player, CardInfo, bool>)Validate);
			}
		}

		public static bool IsCharacter(CardInfo card)
		{
			if ((Object)(object)card != (Object)null)
			{
				return (Object)(object)((Component)card).GetComponent<CharacterCard>() != (Object)null;
			}
			return false;
		}

		public static CharacterCard CharacterOf(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player.data == (Object)null || player.data.currentCards == null)
			{
				return null;
			}
			foreach (CardInfo currentCard in player.data.currentCards)
			{
				if (!((Object)(object)currentCard == (Object)null))
				{
					CharacterCard component = ((Component)currentCard).GetComponent<CharacterCard>();
					if ((Object)(object)component != (Object)null)
					{
						return component;
					}
				}
			}
			return null;
		}

		private static bool Validate(Player player, CardInfo card)
		{
			bool flag = IsCharacter(card);
			if (!RepentancePlugin.CharacterSelectEnabled.Value)
			{
				return !flag;
			}
			if (Active && (Object)(object)CharacterOf(player) == (Object)null)
			{
				return flag;
			}
			return !flag;
		}
	}
	internal static class DebugTools
	{
		private static int nextCharacter;

		private static int nextItem;

		private static Player LocalPlayer()
		{
			if ((Object)(object)PlayerManager.instance == (Object)null)
			{
				return null;
			}
			return ((IEnumerable<Player>)PlayerManager.instance.players).FirstOrDefault((Func<Player, bool>)((Player p) => (Object)(object)p != (Object)null && (Object)(object)p.data != (Object)null && (Object)(object)p.data.view != (Object)null && p.data.view.IsMine));
		}

		public static void Tick()
		{
			if (RepentancePlugin.DebugKeys == null || !RepentancePlugin.DebugKeys.Value)
			{
				return;
			}
			try
			{
				if (Input.GetKeyDown((KeyCode)292))
				{
					((BaseUnityPlugin)RepentancePlugin.Instance).Config.Reload();
					RepentancePlugin.Log.LogInfo((object)$"[debug] config reloaded: ArtSize={RepentancePlugin.ArtScale.Value} ArtOffsetY={RepentancePlugin.ArtOffsetY.Value}");
				}
				if (!PhotonNetwork.OfflineMode)
				{
					return;
				}
				Player val = LocalPlayer();
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				if (Input.GetKeyDown((KeyCode)286))
				{
					List<CardInfo> list = CardRegistry.Characters.ToList();
					if (list.Count > 0)
					{
						CardInfo val2 = list[nextCharacter++ % list.Count];
						RepentancePlugin.Log.LogInfo((object)("[debug] giving character " + val2.cardName));
						Cards.instance.AddCardToPlayer(val, val2, false, "", 0f, 0f, true);
					}
				}
				if (Input.GetKeyDown((KeyCode)287))
				{
					List<CardInfo> list2 = CardRegistry.Items.OrderBy((CardInfo c) => c.cardName).ToList();
					if (list2.Count > 0)
					{
						CardInfo val3 = list2[nextItem++ % list2.Count];
						RepentancePlugin.Log.LogInfo((object)("[debug] giving item " + val3.cardName));
						Cards.instance.AddCardToPlayer(val, val3, false, "", 0f, 0f, true);
					}
				}
				if (Input.GetKeyDown((KeyCode)288))
				{
					((Weapon)val.data.weaponHandler.gun).Attack(1f, true, 1f, 1f, false);
				}
				if (Input.GetKeyDown((KeyCode)289))
				{
					val.data.block.TryBlock();
				}
				if (Input.GetKeyDown((KeyCode)290))
				{
					IsaacPlayerState component = ((Component)val).GetComponent<IsaacPlayerState>();
					RepentancePlugin.Log.LogInfo((object)("[debug] cards: " + string.Join(", ", val.data.currentCards.Select((CardInfo c) => c.cardName).ToArray()) + $" | hp {val.data.health:0}/{val.data.maxHealth:0} | dmgMult {(((Object)(object)component != (Object)null) ? component.DamageMultiplier() : 1f):0.00} | mantle {(((Object)(object)component != (Object)null) ? component.MantleCharges : 0)}" + $" | gun dmg {val.data.weaponHandler.gun.damage:0.00} atk {val.data.weaponHandler.gun.attackSpeed:0.00}"));
				}
				if (Input.GetKeyDown((KeyCode)291))
				{
					IsaacPlayerState.OnBattleStartAll();
					bool flag = Transformations.CheckAllPlayers();
					RepentancePlugin.Log.LogInfo((object)("[debug] battle-start refresh, transformation awarded: " + flag));
				}
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogWarning((object)("[debug] " + ex));
			}
		}
	}
	internal static class EnemyUtil
	{
		public static bool IsAliveEnemy(Player me, Player other)
		{
			if ((Object)(object)other == (Object)null || (Object)(object)me == (Object)null || (Object)(object)other == (Object)(object)me)
			{
				return false;
			}
			if (other.teamID == me.teamID)
			{
				return false;
			}
			if ((Object)(object)other.data == (Object)null || other.data.dead || !other.data.isPlaying)
			{
				return false;
			}
			if (!((Component)other).gameObject.activeInHierarchy)
			{
				return false;
			}
			return true;
		}

		public static Player ClosestEnemy(Player me, Vector3 from, bool needVision)
		{
			//IL_003a: 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_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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)PlayerManager.instance == (Object)null)
			{
				return null;
			}
			Player result = null;
			float num = float.MaxValue;
			foreach (Player player in PlayerManager.instance.players)
			{
				if (!IsAliveEnemy(me, player))
				{
					continue;
				}
				float num2 = Vector2.Distance(Vector2.op_Implicit(from), Vector2.op_Implicit(((Component)player).transform.position));
				if (num2 >= num)
				{
					continue;
				}
				if (needVision)
				{
					CanSeeInfo val = PlayerManager.instance.CanSeePlayer(Vector2.op_Implicit(from), player);
					if (val == null || !val.canSee)
					{
						continue;
					}
				}
				result = player;
				num = num2;
			}
			return result;
		}
	}
	public enum IsaacSet
	{
		None,
		Guppy,
		Seraphim,
		Leviathan,
		Spun,
		FunGuy
	}
	public abstract class IsaacCard : CustomCard
	{
		public abstract string Title { get; }

		public abstract string Quote { get; }

		public virtual string Effect => null;

		public abstract Rarity CardRarity { get; }

		public abstract CardThemeColorType Theme { get; }

		public virtual int IsaacId => 0;

		public virtual int IsaacTrinketId => 0;

		public virtual string IsaacArtPath => null;

		public abstract string FallbackArt { get; }

		public virtual bool Hidden => false;

		public virtual IsaacSet Set => IsaacSet.None;

		public virtual string[] BorrowedEffects => null;

		public abstract CardInfoStat[] StatLines { get; }

		public virtual void ApplyTemplate(Gun gun, CharacterStatModifiers stats, Block block)
		{
		}

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

		protected static CardInfoStat Up(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 = true,
				stat = stat,
				amount = amount,
				simepleAmount = (SimpleAmount)0
			};
		}

		protected static CardInfoStat Down(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 = false,
				stat = stat,
				amount = amount,
				simepleAmount = (SimpleAmount)0
			};
		}

		protected static CardInfoStat DevilDeal(string amount)
		{
			return Down("Devil deal: HP", amount);
		}

		public override void SetupCard(CardInfo cardInfo, Gun gun, ApplyCardStats cardStats, CharacterStatModifiers statModifiers, Block block)
		{
			cardInfo.allowMultiple = true;
			try
			{
				ApplyTemplate(gun, statModifiers, block);
			}
			catch (Exception arg)
			{
				RepentancePlugin.Log.LogError((object)$"[{Title}] template error: {arg}");
			}
			if (BorrowedEffects != null && BorrowedEffects.Length != 0)
			{
				VanillaEffects.Borrow(gun, BorrowedEffects, Title);
			}
		}

		public override void OnAddCard(Player player, Gun gun, GunAmmo gunAmmo, CharacterData data, HealthHandler health, Gravity gravity, Block block, CharacterStatModifiers characterStats)
		{
			try
			{
				ExtensionMethods.GetOrAddComponent<IsaacPlayerState>(((Component)player).gameObject, false).MarkDirty();
				OnPicked(player, gun, gunAmmo, data, health, gravity, block, characterStats);
			}
			catch (Exception arg)
			{
				RepentancePlugin.Log.LogError((object)$"[{Title}] OnAddCard error: {arg}");
			}
		}

		public override void OnRemoveCard(Player player, Gun gun, GunAmmo gunAmmo, CharacterData data, HealthHandler health, Gravity gravity, Block block, CharacterStatModifiers characterStats)
		{
			try
			{
				IsaacPlayerState component = ((Component)player).GetComponent<IsaacPlayerState>();
				if ((Object)(object)component != (Object)null)
				{
					component.MarkDirty();
				}
			}
			catch (Exception arg)
			{
				RepentancePlugin.Log.LogError((object)$"[{Title}] OnRemoveCard error: {arg}");
			}
		}

		protected override string GetTitle()
		{
			return Title;
		}

		protected override string GetDescription()
		{
			string text = "\"" + Quote + "\"";
			if (!string.IsNullOrEmpty(Effect))
			{
				text = text + "\n" + Effect;
			}
			if (Set != IsaacSet.None)
			{
				text = text + "\n<size=70%><color=#bbbbbb>" + Transformations.SetLabel(Set) + "</color></size>";
			}
			return text;
		}

		protected override GameObject GetCardArt()
		{
			try
			{
				return ArtManager.GetArtTemplate(this);
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogWarning((object)("[" + Title + "] art error: " + ex.Message));
				return null;
			}
		}

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

		protected override CardInfoStat[] GetStats()
		{
			return (CardInfoStat[])(((object)StatLines) ?? ((object)new CardInfoStat[0]));
		}

		protected override CardThemeColorType GetTheme()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return Theme;
		}

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

		public override bool GetEnabled()
		{
			return !Hidden;
		}
	}
	internal static class IsaacLocator
	{
		public const string IsaacFolderName = "The Binding of Isaac Rebirth";

		public const string ExtractedFolderName = "extracted_resources";

		public static string FindIsaacDir()
		{
			List<string> list = new List<string>();
			try
			{
				string text = RepentancePlugin.IsaacInstallPath?.Value;
				if (!string.IsNullOrWhiteSpace(text))
				{
					list.Add(text.Trim().Trim(new char[1] { '"' }));
				}
			}
			catch
			{
			}
			try
			{
				string text2 = Directory.GetParent(Paths.GameRootPath)?.FullName;
				if (text2 != null)
				{
					list.Add(Path.Combine(text2, "The Binding of Isaac Rebirth"));
				}
			}
			catch
			{
			}
			foreach (string item in SteamLibraries())
			{
				list.Add(Path.Combine(item, "steamapps", "common", "The Binding of Isaac Rebirth"));
			}
			list.Add(Path.Combine("C:\\Program Files (x86)\\Steam\\steamapps\\common", "The Binding of Isaac Rebirth"));
			list.Add(Path.Combine("C:\\Program Files\\Steam\\steamapps\\common", "The Binding of Isaac Rebirth"));
			foreach (string item2 in list.Distinct())
			{
				try
				{
					if (Directory.Exists(item2) && (File.Exists(Path.Combine(item2, "isaac-ng.exe")) || Directory.Exists(Path.Combine(item2, "resources"))))
					{
						return item2;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static IEnumerable<string> SteamLibraries()
		{
			List<string> list = new List<string>();
			try
			{
				if (Registry.GetValue("HKEY_CURRENT_USER\\Software\\Valve\\Steam", "SteamPath", null) is string text && !string.IsNullOrEmpty(text))
				{
					list.Add(text.Replace('/', '\\'));
				}
			}
			catch
			{
			}
			try
			{
				if (Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Valve\\Steam", "InstallPath", null) is string text2 && !string.IsNullOrEmpty(text2))
				{
					list.Add(text2);
				}
			}
			catch
			{
			}
			list.Add("C:\\Program Files (x86)\\Steam");
			List<string> list2 = new List<string>();
			foreach (string item in list.Distinct())
			{
				list2.Add(item);
				try
				{
					string path = Path.Combine(item, "steamapps", "libraryfolders.vdf");
					if (!File.Exists(path))
					{
						continue;
					}
					foreach (Match item2 in Regex.Matches(File.ReadAllText(path), "\"path\"\\s+\"([^\"]+)\""))
					{
						list2.Add(item2.Groups[1].Value.Replace("\\\\", "\\"));
					}
				}
				catch
				{
				}
			}
			return list2.Distinct();
		}

		public static List<string> FindGfxRoots(string isaacDir)
		{
			List<string> list = new List<string>();
			if (string.IsNullOrEmpty(isaacDir))
			{
				return list;
			}
			string[] array = new string[2]
			{
				Path.Combine(isaacDir, "extracted_resources"),
				isaacDir
			};
			foreach (string path in array)
			{
				string[] array2 = new string[2] { "resources-dlc3", "resources" };
				foreach (string path2 in array2)
				{
					string text = Path.Combine(Path.Combine(path, path2), "gfx");
					try
					{
						if (Directory.Exists(text))
						{
							list.Add(text);
						}
					}
					catch
					{
					}
				}
			}
			return list;
		}

		public static bool HasItemSprites(List<string> gfxRoots)
		{
			foreach (string gfxRoot in gfxRoots)
			{
				try
				{
					if (Directory.Exists(Path.Combine(Path.Combine(gfxRoot, "items"), "collectibles")))
					{
						return true;
					}
				}
				catch
				{
				}
			}
			return false;
		}

		public static string FindGfxFile(List<string> gfxRoots, string relative)
		{
			string path = relative.Replace('/', Path.DirectorySeparatorChar);
			foreach (string gfxRoot in gfxRoots)
			{
				try
				{
					string text = Path.Combine(gfxRoot, path);
					if (File.Exists(text))
					{
						return text;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		public static string FindCollectible(List<string> gfxRoots, int id)
		{
			return FindFile(gfxRoots, Path.Combine("items", "collectibles"), $"collectibles_{id:000}_");
		}

		public static string FindTrinket(List<string> gfxRoots, int id)
		{
			return FindFile(gfxRoots, Path.Combine("items", "trinkets"), $"trinket_{id:000}_");
		}

		private static string FindFile(List<string> roots, string sub, string prefix)
		{
			foreach (string root in roots)
			{
				try
				{
					string path = Path.Combine(root, sub);
					if (Directory.Exists(path))
					{
						string text = (from f in Directory.GetFiles(path, prefix + "*.png")
							orderby f.Length
							select f).FirstOrDefault();
						if (text != null)
						{
							return text;
						}
					}
				}
				catch
				{
				}
			}
			return null;
		}
	}
	public class IsaacPlayerState : MonoBehaviour
	{
		public static readonly List<IsaacPlayerState> All = new List<IsaacPlayerState>();

		public Player player;

		public CharacterData data;

		private Gun gun;

		private Block block;

		private CharacterStatModifiers stats;

		private readonly Dictionary<string, int> counts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

		private bool dirty = true;

		private int lastCardCount = -1;

		private bool hooked;

		public int MantleCharges;

		private int bloodyLustStacks;

		private float belialTimer;

		private float lastFlyTime;

		private float bobbyCooldown;

		private SimulatedGun burstGun;

		private SimulatedGun flyGun;

		private SimulatedGun bobbyGun;

		private MantleVisual mantleVisual;

		private FamiliarVisual bobby;

		private CharacterHeadVisual head;

		private float headCheckTimer;

		private bool initialized;

		private string pendingAnnouncement;

		private bool IsMine
		{
			get
			{
				if ((Object)(object)data != (Object)null && (Object)(object)data.view != (Object)null)
				{
					if (!data.view.IsMine)
					{
						return PhotonNetwork.OfflineMode;
					}
					return true;
				}
				return false;
			}
		}

		private void EnsureInit()
		{
			if (!initialized)
			{
				initialized = true;
				player = ((Component)this).GetComponent<Player>();
				data = ((Component)this).GetComponent<CharacterData>();
				block = ((Component)this).GetComponent<Block>();
				stats = ((Component)this).GetComponent<CharacterStatModifiers>();
				if (!All.Contains(this))
				{
					All.Add(this);
				}
			}
		}

		private void Awake()
		{
			EnsureInit();
		}

		private void Start()
		{
			EnsureInit();
			Hook();
		}

		private void Hook()
		{
			EnsureInit();
			if (hooked)
			{
				return;
			}
			try
			{
				gun = data.weaponHandler.gun;
				gun.ShootPojectileAction = (Action<GameObject>)Delegate.Combine(gun.ShootPojectileAction, new Action<GameObject>(OnShootProjectile));
				block.BlockAction = (Action<BlockTriggerType>)Delegate.Combine(block.BlockAction, new Action<BlockTriggerType>(OnBlock));
				stats.WasDealtDamageAction = (Action<Vector2, bool>)Delegate.Combine(stats.WasDealtDamageAction, new Action<Vector2, bool>(OnWasDealtDamage));
				stats.DealtDamageAction = (Action<Vector2, bool>)Delegate.Combine(stats.DealtDamageAction, new Action<Vector2, bool>(OnDealtDamage));
				hooked = true;
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogError((object)("IsaacPlayerState hook failed: " + ex));
			}
		}

		private void OnDestroy()
		{
			All.Remove(this);
			try
			{
				if (hooked)
				{
					if ((Object)(object)gun != (Object)null)
					{
						gun.ShootPojectileAction = (Action<GameObject>)Delegate.Remove(gun.ShootPojectileAction, new Action<GameObject>(OnShootProjectile));
					}
					if ((Object)(object)block != (Object)null)
					{
						block.BlockAction = (Action<BlockTriggerType>)Delegate.Remove(block.BlockAction, new Action<BlockTriggerType>(OnBlock));
					}
					if ((Object)(object)stats != (Object)null)
					{
						stats.WasDealtDamageAction = (Action<Vector2, bool>)Delegate.Remove(stats.WasDealtDamageAction, new Action<Vector2, bool>(OnWasDealtDamage));
						stats.DealtDamageAction = (Action<Vector2, bool>)Delegate.Remove(stats.DealtDamageAction, new Action<Vector2, bool>(OnDealtDamage));
					}
				}
			}
			catch
			{
			}
			if ((Object)(object)bobby != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)bobby).gameObject);
			}
		}

		public void MarkDirty()
		{
			EnsureInit();
			dirty = true;
		}

		public int Count(string title)
		{
			EnsureInit();
			EnsureCounts();
			if (!counts.TryGetValue(title, out var value))
			{
				return 0;
			}
			return value;
		}

		public bool Has(string title)
		{
			return Count(title) > 0;
		}

		public int DistinctOwned(IEnumerable<string> titles)
		{
			EnsureInit();
			EnsureCounts();
			return titles.Count((string t) => counts.ContainsKey(t));
		}

		private void EnsureCounts()
		{
			if ((Object)(object)data == (Object)null || data.currentCards == null || (!dirty && data.currentCards.Count == lastCardCount))
			{
				return;
			}
			counts.Clear();
			foreach (CardInfo currentCard in data.currentCards)
			{
				if (!((Object)(object)currentCard == (Object)null))
				{
					string key = currentCard.cardName ?? "";
					counts[key] = ((!counts.TryGetValue(key, out var value)) ? 1 : (value + 1));
				}
			}
			lastCardCount = data.currentCards.Count;
			dirty = false;
		}

		public static void OnBattleStartAll()
		{
			IsaacPlayerState[] array = All.ToArray();
			foreach (IsaacPlayerState isaacPlayerState in array)
			{
				if (!((Object)(object)isaacPlayerState == (Object)null))
				{
					isaacPlayerState.dirty = true;
					isaacPlayerState.MantleCharges = isaacPlayerState.Count("Holy Mantle");
					isaacPlayerState.bloodyLustStacks = 0;
					isaacPlayerState.belialTimer = 0f;
					isaacPlayerState.bobbyCooldown = 1.5f;
					isaacPlayerState.Transformations_Announce();
				}
			}
		}

		public static void OnPointEndAll()
		{
			IsaacPlayerState[] array = All.ToArray();
			foreach (IsaacPlayerState isaacPlayerState in array)
			{
				if (!((Object)(object)isaacPlayerState == (Object)null))
				{
					isaacPlayerState.bloodyLustStacks = 0;
					isaacPlayerState.belialTimer = 0f;
				}
			}
		}

		public static void ResetAllForNewGame()
		{
			IsaacPlayerState[] array = All.ToArray();
			foreach (IsaacPlayerState isaacPlayerState in array)
			{
				if (!((Object)(object)isaacPlayerState == (Object)null))
				{
					isaacPlayerState.MantleCharges = 0;
					isaacPlayerState.bloodyLustStacks = 0;
					isaacPlayerState.belialTimer = 0f;
					isaacPlayerState.dirty = true;
					isaacPlayerState.burstGun = null;
					isaacPlayerState.flyGun = null;
					isaacPlayerState.bobbyGun = null;
				}
			}
		}

		public void QueueAnnouncement(string text)
		{
			pendingAnnouncement = text;
		}

		private void Transformations_Announce()
		{
			//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_0045: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(pendingAnnouncement))
			{
				return;
			}
			string text = pendingAnnouncement;
			pendingAnnouncement = null;
			if (!RepentancePlugin.AnnounceTransformations.Value)
			{
				return;
			}
			try
			{
				Color color = PlayerSkinBank.GetPlayerSkinColors(player.playerID).color;
				UIHandler.instance.DisplayScreenText(color, text, 1f);
			}
			catch
			{
			}
		}

		public void EnsureGuns()
		{
			EnsureInit();
			if ((Object)(object)burstGun == (Object)null)
			{
				burstGun = NewSimGun("RC_BurstGun");
			}
			if ((Object)(object)flyGun == (Object)null)
			{
				flyGun = NewSimGun("RC_FlyGun");
			}
			if ((Object)(object)bobbyGun == (Object)null)
			{
				bobbyGun = NewSimGun("RC_BobbyGun");
			}
		}

		private static SimulatedGun NewSimGun(string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return new GameObject(name).AddComponent<SimulatedGun>();
		}

		private void PrepareFrom(SimulatedGun sg)
		{
			sg.CopyGunStatsExceptActions(gun);
			((Gun)sg).numberOfProjectiles = 1;
			((Gun)sg).bursts = 0;
			((Gun)sg).spread = 0f;
			((Gun)sg).evenSpread = 0f;
			((Gun)sg).timeBetweenBullets = 0f;
			((Gun)sg).multiplySpread = 1f;
		}

		private static void DebugLog(string msg)
		{
			if (RepentancePlugin.DebugKeys != null && RepentancePlugin.DebugKeys.Value)
			{
				RepentancePlugin.Log.LogInfo((object)("[debug] " + msg));
			}
		}

		private void FireRing(int bullets, float damageM)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			DebugLog($"Tammy's Head ring: {bullets} tears (mine={IsMine}, gun={(Object)(object)burstGun != (Object)null})");
			if (IsMine && !((Object)(object)burstGun == (Object)null))
			{
				PrepareFrom(burstGun);
				Vector3 position = ((Component)this).transform.position;
				float num = Random.Range(0f, 360f);
				Vector3 val = default(Vector3);
				for (int i = 0; i < bullets; i++)
				{
					float num2 = (num + (float)i * 360f / (float)bullets) * ((float)Math.PI / 180f);
					((Vector3)(ref val))..ctor(Mathf.Cos(num2), Mathf.Sin(num2), 0f);
					burstGun.SimulatedAttack(player.playerID, position + val * 0.9f, val, 1f, damageM, (Transform)null, false);
				}
			}
		}

		private void FireFlies(int flies, float damageM)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			DebugLog($"blue flies: {flies} (mine={IsMine}, gun={(Object)(object)flyGun != (Object)null})");
			if (!IsMine || (Object)(object)flyGun == (Object)null)
			{
				return;
			}
			PrepareFrom(flyGun);
			((Gun)flyGun).objectsToSpawn = VanillaEffects.Get("homing");
			((Gun)flyGun).projectileColor = new Color(0.35f, 0.55f, 1f, 1f);
			((Gun)flyGun).gravity = 0f;
			((Gun)flyGun).projectileSpeed = Mathf.Min(gun.projectileSpeed, 1f) * 0.55f;
			((Gun)flyGun).reflects = 0;
			((Gun)flyGun).ignoreWalls = false;
			((Gun)flyGun).size = 0f;
			Vector3 val = ((Component)this).transform.position + Vector3.up * 0.8f;
			Player val2 = EnemyUtil.ClosestEnemy(player, val, needVision: false);
			for (int i = 0; i < flies; i++)
			{
				Vector3 val3;
				if (!((Object)(object)val2 != (Object)null))
				{
					Vector2 insideUnitCircle = Random.insideUnitCircle;
					val3 = Vector2.op_Implicit(((Vector2)(ref insideUnitCircle)).normalized);
				}
				else
				{
					Vector3 val4 = ((Component)val2).transform.position - val;
					val3 = ((Vector3)(ref val4)).normalized;
				}
				Vector3 val5 = val3;
				val5 = Quaternion.Euler(0f, 0f, Random.Range(-35f, 35f)) * val5;
				if (val5 == Vector3.zero)
				{
					val5 = Vector3.up;
				}
				flyGun.SimulatedAttack(player.playerID, val, val5, 1f, damageM, (Transform)null, false);
			}
		}

		private void OnShootProjectile(GameObject bullet)
		{
			try
			{
				ProjectileHit component = bullet.GetComponent<ProjectileHit>();
				if (!((Object)(object)component == (Object)null))
				{
					float num = DamageMultiplier();
					if (Math.Abs(num - 1f) > 0.001f)
					{
						component.damage *= num;
					}
					int num2 = Count("Godhead");
					if (num2 > 0 && (Object)(object)bullet.GetComponent<GodheadAura>() == (Object)null)
					{
						GodheadAura godheadAura = bullet.AddComponent<GodheadAura>();
						godheadAura.owner = player;
						godheadAura.stacks = num2;
					}
				}
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogWarning((object)("OnShootProjectile: " + ex.Message));
			}
		}

		public float DamageMultiplier()
		{
			float num = 1f;
			if (Count("Bloody Lust") > 0 && bloodyLustStacks > 0)
			{
				num *= 1f + 0.15f * (float)bloodyLustStacks;
			}
			float num2 = ((data.maxHealth > 0f) ? Mathf.Clamp01(data.health / data.maxHealth) : 1f);
			int num3 = Count("Whore of Babylon");
			if (num3 > 0 && num2 <= 0.5f)
			{
				num *= 1f + 0.5f * (float)num3;
			}
			int num4 = Count("Adrenaline");
			if (num4 > 0)
			{
				num *= 1f + (1f - num2) * (float)num4;
			}
			int num5 = Count("The Book of Belial");
			if (num5 > 0 && belialTimer > 0f)
			{
				num *= 1f + 0.6f * (float)num5;
			}
			return num;
		}

		public float SpeedMultiplierBonus()
		{
			float num = ((data.maxHealth > 0f) ? Mathf.Clamp01(data.health / data.maxHealth) : 1f);
			if (Count("Whore of Babylon") <= 0 || !(num <= 0.5f))
			{
				return 1f;
			}
			return 1.2f;
		}

		private void OnBlock(BlockTriggerType trigger)
		{
			try
			{
				if (Count("The Book of Belial") > 0)
				{
					belialTimer = 3f;
				}
				int num = Count("Tammy's Head");
				if (num > 0)
				{
					FireRing(6 + 4 * num, 0.5f);
				}
				int num2 = Count("Guppy's Head");
				if (num2 > 0)
				{
					FireFlies(2 + num2, 0.35f);
				}
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogWarning((object)("OnBlock: " + ex.Message));
			}
		}

		private void OnWasDealtDamage(Vector2 damage, bool selfDamage)
		{
			if (!selfDamage)
			{
				int num = Count("Bloody Lust");
				if (num > 0)
				{
					bloodyLustStacks = Mathf.Min(bloodyLustStacks + 1, 6 * num);
				}
			}
		}

		private void OnDealtDamage(Vector2 damage, bool selfDamage)
		{
			if (selfDamage || ((Vector2)(ref damage)).magnitude < 1f)
			{
				return;
			}
			try
			{
				if (Has("Guppy") && Time.time - lastFlyTime > 0.35f)
				{
					lastFlyTime = Time.time;
					FireFlies(1, 0.3f);
				}
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogWarning((object)("OnDealtDamage: " + ex.Message));
			}
		}

		private void Update()
		{
			if (!((Object)(object)data == (Object)null))
			{
				if (!hooked)
				{
					Hook();
				}
				if (belialTimer > 0f)
				{
					belialTimer -= TimeHandler.deltaTime;
				}
				UpdateMantleVisual();
				UpdateBobby();
				UpdateCharacterHead();
			}
		}

		private void UpdateCharacterHead()
		{
			headCheckTimer -= Time.deltaTime;
			if (headCheckTimer > 0f)
			{
				return;
			}
			headCheckTimer = 0.5f;
			try
			{
				CharacterCard characterCard = (RepentancePlugin.ShowCharacterHeads.Value ? CharacterSelect.CharacterOf(player) : null);
				string text = (((Object)(object)characterCard != (Object)null) ? (characterCard.SkinSheet + "|" + characterCard.CostumeSheet) : null);
				Sprite val = (((Object)(object)characterCard != (Object)null) ? ArtManager.BuildCharacterHead(characterCard.SkinSheet, characterCard.CostumeSheet) : null);
				if ((Object)(object)val == (Object)null)
				{
					if ((Object)(object)head != (Object)null)
					{
						((Component)head).gameObject.SetActive(false);
					}
					return;
				}
				if ((Object)(object)head == (Object)null)
				{
					head = CharacterHeadVisual.Create(this, val, text);
				}
				else if (head.Key != text)
				{
					head.Set(val, text);
				}
				if (!((Component)head).gameObject.activeSelf)
				{
					((Component)head).gameObject.SetActive(true);
				}
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogWarning((object)("Character head: " + ex.Message));
				headCheckTimer = 5f;
			}
		}

		private void UpdateMantleVisual()
		{
			bool flag = MantleCharges > 0 && data.isPlaying && !data.dead;
			if (flag && (Object)(object)mantleVisual == (Object)null)
			{
				mantleVisual = MantleVisual.Create(this);
			}
			if ((Object)(object)mantleVisual != (Object)null)
			{
				mantleVisual.SetVisible(flag);
			}
		}

		public void OnMantleBroken()
		{
			if ((Object)(object)mantleVisual != (Object)null)
			{
				mantleVisual.Break();
			}
		}

		private void UpdateBobby()
		{
			//IL_00c8: 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_00d4: 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_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			int num = Count("Brother Bobby");
			if (num <= 0)
			{
				if ((Object)(object)bobby != (Object)null)
				{
					bobby.Enabled = false;
				}
				return;
			}
			if ((Object)(object)bobby == (Object)null)
			{
				bobby = FamiliarVisual.Create(this, ArtManager.GetSprite(8, "bobby"));
			}
			bobby.Enabled = true;
			if (!data.isPlaying || data.dead || !((Component)this).gameObject.activeInHierarchy)
			{
				return;
			}
			bobbyCooldown -= TimeHandler.deltaTime;
			if (bobbyCooldown > 0f || !IsMine || (Object)(object)bobbyGun == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)bobby).transform.position;
			Player val = EnemyUtil.ClosestEnemy(player, position, needVision: true);
			if (!((Object)(object)val == (Object)null) && !(Vector3.Distance(position, ((Component)val).transform.position) > 30f))
			{
				bobbyCooldown = 1.25f / (float)num;
				PrepareFrom(bobbyGun);
				((Gun)bobbyGun).damage = 1f;
				((Gun)bobbyGun).objectsToSpawn = (ObjectsToSpawn[])(object)new ObjectsToSpawn[0];
				((Gun)bobbyGun).reflects = 0;
				((Gun)bobbyGun).projectileColor = Color.black;
				((Gun)bobbyGun).gravity = 0.5f;
				((Gun)bobbyGun).projectileSpeed = 1f;
				Vector3 val2 = ((Component)val).transform.position - position;
				Vector3 normalized = ((Vector3)(ref val2)).normalized;
				if (normalized != Vector3.zero)
				{
					bobbyGun.SimulatedAttack(player.playerID, position, normalized, 1f, 0.3f, (Transform)null, false);
				}
			}
		}
	}
	internal static class SpriteExtractor
	{
		private static readonly string[] Archives = new string[4] { "graphics.a", "afterbirth.a", "afterbirthp.a", "repentance.a" };

		public static volatile bool Running;

		public static volatile bool Finished;

		public static volatile bool Succeeded;

		public static string Message = "";

		[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		private static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes);

		public static string ExtractorPath(string isaacDir)
		{
			return Path.Combine(Path.Combine(Path.Combine(isaacDir, "tools"), "ResourceExtractor"), "ResourceExtractor.exe");
		}

		public static bool CanExtract(string isaacDir)
		{
			try
			{
				return !string.IsNullOrEmpty(isaacDir) && File.Exists(ExtractorPath(isaacDir)) && Directory.Exists(Path.Combine(Path.Combine(isaacDir, "resources"), "packed"));
			}
			catch
			{
				return false;
			}
		}

		public static void StartInBackground(string isaacDir)
		{
			if (Running)
			{
				return;
			}
			Running = true;
			Finished = false;
			Thread thread = new Thread((ThreadStart)delegate
			{
				try
				{
					Succeeded = Extract(isaacDir);
				}
				catch (Exception ex)
				{
					Succeeded = false;
					Message = ex.Message;
				}
				finally
				{
					Running = false;
					Finished = true;
				}
			});
			thread.IsBackground = true;
			thread.Start();
		}

		private static bool Extract(string isaacDir)
		{
			string path = Path.Combine(isaacDir, "extracted_resources");
			string text = Path.Combine(path, "_rc_staging");
			string text2 = Path.Combine(path, "_rc_output");
			SafeDelete(text);
			SafeDelete(text2);
			string path2 = Path.Combine(Path.Combine(isaacDir, "resources"), "packed");
			string text3 = Path.Combine(Path.Combine(text, "resources"), "packed");
			Directory.CreateDirectory(text3);
			bool flag = true;
			string[] archives = Archives;
			foreach (string path3 in archives)
			{
				string text4 = Path.Combine(path2, path3);
				if (File.Exists(text4) && !CreateHardLink(Path.Combine(text3, path3), text4, IntPtr.Zero))
				{
					flag = false;
					break;
				}
			}
			string text5 = (flag ? text : isaacDir);
			Directory.CreateDirectory(text2);
			string text6 = ExtractorPath(isaacDir);
			ProcessStartInfo processStartInfo = new ProcessStartInfo();
			processStartInfo.FileName = text6;
			processStartInfo.Arguments = "\"" + text5 + "\" \"" + text2 + "\"";
			processStartInfo.WorkingDirectory = Path.GetDirectoryName(text6);
			processStartInfo.UseShellExecute = false;
			processStartInfo.CreateNoWindow = true;
			processStartInfo.RedirectStandardOutput = true;
			processStartInfo.RedirectStandardError = true;
			processStartInfo.RedirectStandardInput = true;
			ProcessStartInfo startInfo = processStartInfo;
			using (Process process = new Process
			{
				StartInfo = startInfo
			})
			{
				process.OutputDataReceived += delegate
				{
				};
				process.ErrorDataReceived += delegate
				{
				};
				process.Start();
				try
				{
					process.StandardInput.Close();
				}
				catch
				{
				}
				process.BeginOutputReadLine();
				process.BeginErrorReadLine();
				if (!process.WaitForExit(600000))
				{
					try
					{
						process.Kill();
					}
					catch
					{
					}
					Message = "ResourceExtractor timed out";
				}
			}
			int num = 0;
			archives = new string[2] { "resources", "resources-dlc3" };
			foreach (string path4 in archives)
			{
				string path5 = Path.Combine(Path.Combine(text2, path4), "gfx");
				string path6 = Path.Combine(Path.Combine(path, path4), "gfx");
				num += CopyMatching(Path.Combine(Path.Combine(path5, "items"), "collectibles"), Path.Combine(Path.Combine(path6, "items"), "collectibles"), "*.png");
				num += CopyMatching(Path.Combine(Path.Combine(path5, "items"), "trinkets"), Path.Combine(Path.Combine(path6, "items"), "trinkets"), "*.png");
				num += CopyMatching(Path.Combine(Path.Combine(path5, "ui"), "stage"), Path.Combine(Path.Combine(path6, "ui"), "stage"), "playerportrait_*.png");
				num += CopyMatching(Path.Combine(Path.Combine(path5, "characters"), "costumes"), Path.Combine(Path.Combine(path6, "characters"), "costumes"), "character_0*.png");
			}
			SafeDelete(text2);
			SafeDelete(text);
			Message = $"unpacked {num} item sprites";
			return num > 0;
		}

		private static int CopyMatching(string from, string to, string pattern)
		{
			if (!Directory.Exists(from))
			{
				return 0;
			}
			Directory.CreateDirectory(to);
			int num = 0;
			string[] files = Directory.GetFiles(from, pattern);
			foreach (string text in files)
			{
				string fileName = Path.GetFileName(text);
				if (!fileName.EndsWith("_black.png") && !fileName.EndsWith("_blue.png") && !fileName.EndsWith("_green.png") && !fileName.EndsWith("_grey.png") && !fileName.EndsWith("_red.png") && !fileName.EndsWith("_white.png"))
				{
					File.Copy(text, Path.Combine(to, fileName), overwrite: true);
					num++;
				}
			}
			return num;
		}

		private static void SafeDelete(string dir)
		{
			try
			{
				if (Directory.Exists(dir))
				{
					Directory.Delete(dir, recursive: true);
				}
			}
			catch
			{
			}
		}
	}
	internal static class Transformations
	{
		private class Def
		{
			public IsaacSet Set;

			public string CardTitle;

			public string Banner;

			public string[] Items;
		}

		public const int ItemsNeeded = 3;

		private static readonly Def[] Defs = new Def[5]
		{
			new Def
			{
				Set = IsaacSet.Guppy,
				CardTitle = "Guppy",
				Banner = "GUPPY!",
				Items = new string[6] { "Guppy's Head", "Guppy's Paw", "Guppy's Tail", "Guppy's Hairball", "Guppy's Collar", "Dead Cat" }
			},
			new Def
			{
				Set = IsaacSet.Seraphim,
				CardTitle = "Seraphim",
				Banner = "SERAPHIM!",
				Items = new string[8] { "The Halo", "Holy Grail", "Dead Dove", "Rosary", "Holy Light", "Holy Mantle", "Sacred Heart", "Godhead" }
			},
			new Def
			{
				Set = IsaacSet.Leviathan,
				CardTitle = "Leviathan",
				Banner = "LEVIATHAN!",
				Items = new string[10] { "Pentagram", "The Mark", "Abaddon", "Lord of the Pit", "Spirit of the Night", "Whore of Babylon", "The Book of Belial", "Ceremonial Robes", "The Pact", "Brimstone" }
			},
			new Def
			{
				Set = IsaacSet.Spun,
				CardTitle = "Spun",
				Banner = "SPUN!",
				Items = new string[7] { "Roid Rage", "Synthoil", "Experimental Treatment", "Adrenaline", "Euthanasia", "Growth Hormones", "Speed Ball" }
			},
			new Def
			{
				Set = IsaacSet.FunGuy,
				CardTitle = "Fun Guy",
				Banner = "FUN GUY!",
				Items = new string[6] { "Odd Mushroom (Thin)", "Odd Mushroom (Large)", "1up!", "Blue Cap", "Mini Mush", "Magic Mushroom" }
			}
		};

		private static readonly Dictionary<IsaacSet, CardInfo> hiddenCards = new Dictionary<IsaacSet, CardInfo>();

		public static void RegisterHiddenCard(IsaacSet set, CardInfo card)
		{
			hiddenCards[set] = card;
			try
			{
				Cards.instance.AddHiddenCard(card);
			}
			catch (Exception ex)
			{
				RepentancePlugin.Log.LogError((object)("AddHiddenCard failed: " + ex));
			}
		}

		public static string SetLabel(IsaacSet set)
		{
			return set switch
			{
				IsaacSet.Guppy => "Guppy item", 
				IsaacSet.Seraphim => "Angel item", 
				IsaacSet.Leviathan => "Devil item", 
				IsaacSet.Spun => "Syringe item", 
				IsaacSet.FunGuy => "Mushroom item", 
				_ => "", 
			};
		}

		public static bool CheckAllPlayers()
		{
			if ((Object)(object)PlayerManager.instance == (Object)null)
			{
				return false;
			}
			bool flag = PhotonNetwork.OfflineMode || PhotonNetwork.IsMasterClient;
			bool result = false;
			Player[] array = PlayerManager.instance.players.ToArray();
			foreach (Player val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.data == (Object)null)
				{
					continue;
				}
				IsaacPlayerState orAddComponent = ExtensionMethods.GetOrAddComponent<IsaacPlayerState>(((Component)val).gameObject, false);
				orAddComponent.MarkDirty();
				Def[] defs = Defs;
				foreach (Def def in defs)
				{
					if (orAddComponent.Has(def.CardTitle) || orAddComponent.DistinctOwned(def.Items) < 3 || !hiddenCards.TryGetValue(def.Set, out var value) || (Object)(object)value == (Object)null)
					{
						continue;
					}
					orAddComponent.QueueAnnouncement(def.Banner);
					if (flag)
					{
						try
						{
							Cards.instance.AddCardToPlayer(val, value, false, "", 0f, 0f, true);
							result = true;
							RepentancePlugin.Log.LogInfo((object)$"Player {val.playerID} transformed: {def.CardTitle}");
						}
						catch (Exception ex)
						{
							RepentancePlugin.Log.LogError((object)("Could not award transformation: " + ex));
						}
					}
				}
			}
			return result;
		}
	}
	internal static class VanillaEffects
	{
		private class Pending
		{
			public Gun Gun;

			public string[] Effects;

			public string Owner;
		}

		public const string Homing = "homing";

		public const string Poison = "poison";

		public const string Explosive = "explosive";

		public const string Cold = "cold";

		private static readonly Dictionary<string, string[]> CandidateNames = new Dictionary<string, string[]>
		{
			{
				"homing",
				new string[1] { "Homing" }
			},
			{
				"poison",
				new string[1] { "Poison" }
			},
			{
				"explosive",
				new string[3] { "Explosive bullet", "Explosive Bullet", "Explosive" }
			},
			{
				"cold",
				new string[2] { "Cold bullets", "Cold Bullets" }
			}
		};

		private static readonly List<Pending> pending = new List<Pending>();

		private static readonly Dictionary<string, ObjectsToSpawn[]> cache = new Dictionary<string, ObjectsToSpawn[]>();

		private static string Norm(string s)
		{
			return (s ?? "").Replace(" ", "").Replace("(Clone)", "").ToLowerInvariant();
		}

		private static IEnumerable<CardInfo> AllVanillaCards()
		{
			List<CardInfo> list = new List<CardInfo>();
			try
			{
				if ((Object)(object)CardChoice.instance != (Object)null && CardChoice.instance.cards != null)
				{
					list.AddRange(CardChoice.instance.cards.Where((CardInfo c) => (Object)(object)c != (Object)null));
				}
			}
			catch
			{
			}
			try
			{
				list.AddRange(Cards.all.Where((CardInfo c) => (Object)(object)c != (Object)null));
			}
			catch
			{
			}
			return list.Distinct();
		}

		private static ObjectsToSpawn[] Find(string effect)
		{
			if (cache.TryGetValue(effect, out var value) && value != null)
			{
				return value;
			}
			if (!CandidateNames.TryGetValue(effect, out var value2))
			{
				return null;
			}
			string[] source = value2.Select(Norm).ToArray();
			foreach (CardInfo item in AllVanillaCards())
			{
				string value3 = Norm(((Object)((Component)item).gameObject).name);
				string value4 = Norm(item.cardName);
				if ((source.Contains(value3) || source.Contains(value4)) && !((Object)(object)((Component)item).GetComponent<CustomCard>() != (Object)null))
				{
					Gun component = ((Component)item).GetComponent<Gun>();
					if (!((Object)(object)component == (Object)null) && component.objectsToSpawn != null && component.objectsToSpawn.Length != 0)
					{
						cache[effect] = component.objectsToSpawn;
						return component.objectsToSpawn;
					}
				}
			}
			return null;
		}

		public static void Borrow(Gun gun, string[] effects, string owner)
		{
			if (!TryApply(gun, effects, owner, logMissing: false))
			{
				pending.Add(new Pending
				{
					Gun = gun,
					Effects = effects,
					Owner = owner
				});
			}
		}

		private static bool TryApply(Gun gun, string[] effects, string owner, bool logMissing)
		{
			if ((Object)(object)gun == (Object)null)
			{
				return true;
			}
			List<ObjectsToSpawn> list = new List<ObjectsToSpawn>();
			foreach (string text in effects)
			{
				ObjectsToSpawn[] array = Find(text);
				if (array == null)
				{
					if (logMissing)
					{
						RepentancePlugin.Log.LogWarning((object)("[" + owner + "] could not find vanilla effect '" + text + "'"));
					}
					return false;
				}
				list.AddRange(array);
			}
			List<ObjectsToSpawn> list2 = ((gun.objectsToSpawn != null) ? gun.objectsToSpawn.ToList() : new List<ObjectsToSpawn>());
			foreach (ObjectsToSpawn item in list)
			{
				list2.Add(Clone(item));
			}
			gun.objectsToSpawn = list2.ToArray();
			return true;
		}

		public static ObjectsToSpawn Clone(ObjectsToSpawn o)
		{
			//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_0011: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_0095: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			return new ObjectsToSpawn
			{
				effect = o.effect,
				direction = o.direction,
				spawnOn = o.spawnOn,
				spawnAsChild = o.spawnAsChild,
				numberOfSpawns = o.numberOfSpawns,
				normalOffset = o.normalOffset,
				stickToBigTargets = o.stickToBigTargets,
				stickToAllTargets = o.stickToAllTargets,
				zeroZ = o.zeroZ,
				AddToProjectile = o.AddToProjectile,
				removeScriptsFromProjectileObject = o.removeScriptsFromProjectileObject,
				scaleStacks = o.scaleStacks,
				scaleStackM = o.scaleStackM,
				scaleFromDamage = o.scaleFromDamage,
				stacks = 0
			};
		}

		public static void ResolvePending()
		{
			for (int num = VanillaEffects.pending.Count - 1; num >= 0; num--)
			{
				Pending pending = VanillaEffects.pending[num];
				if (TryApply(pending.Gun, pending.Effects, pending.Owner, logMissing: true))
				{
					VanillaEffects.pending.RemoveAt(num);
				}
			}
		}

		public static ObjectsToSpawn[] Get(string effect)
		{
			return ((IEnumerable<ObjectsToSpawn>)(((object)Find(effect)) ?? ((object)new ObjectsToSpawn[0]))).Select(Clone).ToArray();
		}

		public static void LogVanillaCards()
		{
			ResolvePending();
			string[] array = (from c in AllVanillaCards()
				where (Object)(object)((Component)c).GetComponent<CustomCard>() == (Object)null
				select ((Object)((Component)c).gameObject).name into n
				orderby n
				select n).ToArray();
			RepentancePlugin.Log.LogInfo((object)($"Vanilla cards seen ({array.Length}): " + string.Join(", ", array)));
			foreach (KeyValuePair<string, string[]> candidateName in CandidateNames)
			{
				RepentancePlugin.Log.LogInfo((object)("Vanilla effect '" + candidateName.Key + "': " + ((Find(candidateName.Key) != null) ? "found" : "MISSING")));
			}
		}
	}
}
namespace RepentanceCards.Cards
{
	public class TheHalo : IsaacCard
	{
		public override string Title => "The Halo";

		public override string Quote => "All stats up";

		public override Rarity CardRarity => (Rarity)1;

		public override CardThemeColorType Theme => (CardThemeColorType)3;

		public override int IsaacId => 101;

		public override string FallbackArt => "halo";

		public override IsaacSet Set => IsaacSet.Seraphim;

		public override CardInfoStat[] StatLines => (CardInfoStat[])(object)new CardInfoStat[5]
		{
			IsaacCard.Up("Damage", "+10%"),
			IsaacCard.Up("Attack speed", "+10%"),
			IsaacCard.Up("Shot speed", "+10%"),
			IsaacCard.Up("Move speed", "+10%"),
			IsaacCard.Up("Health", "+10%")
		};

		public override void ApplyTemplate(Gun gun, CharacterStatModifiers stats, Block block)
		{
			gun.damage = 1.1f;
			gun.attackSpeed = 0.9f;
			gun.projectileSpeed = 1.1f;
			stats.movementSpeed = 1.1f;
			stats.health = 1.1f;
		}
	}
	public