Decompiled source of RepentanceCards v1.0.0
RepentanceCards.dll
Decompiled 4 hours ago
The result has been truncated due to the large size, download it to view full contents!
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