using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using DiskCardGame; using HarmonyLib; using InscryptionAPI.Card; using InscryptionAPI.Helpers; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("OldSa_Crimson_Rush_sigil")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OldSa_Crimson_Rush_sigil")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("06293b9e-8de2-401c-8d9c-f9bd1db0b842")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace OLD_SA.CrimsonRush; public static class CrimsonRushAPI { public static FullAbility ability; public static void Init() { AbilityInfo val = ScriptableObject.CreateInstance(); ((Object)val).name = "Crimson Rush"; val.rulebookName = "Crimson Rush"; val.metaCategories = new List { (AbilityMetaCategory)0 }; val.powerLevel = 5; val.opponentUsable = false; val.canStack = false; Texture imageAsTexture = (Texture)(object)TextureHelper.GetImageAsTexture("OldSa_Crimson_Rush.png", (FilterMode)0); FieldInfo field = typeof(AbilityInfo).GetField("rulebookDescription", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(val, "When [creature] attacks, it targets opposing creatures first and gains 1 additional attack after a kill."); } ability = AbilityManager.Add("OLD_SA", val, typeof(CrimsonRushBehaviour), imageAsTexture); } } public class CrimsonRushBehaviour : AbilityBehaviour { private static readonly Dictionary KillCounts = new Dictionary(); public override Ability Ability => CrimsonRushAPI.ability.Id; public static int GetKillCount(PlayableCard card) { if ((Object)(object)card == (Object)null) { return 0; } if (KillCounts.TryGetValue(card, out var value)) { return value; } return 0; } public override bool RespondsToOtherCardDie(PlayableCard card, CardSlot deathSlot, bool fromCombat, PlayableCard killer) { return (Object)(object)killer == (Object)(object)((AbilityBehaviour)this).Card; } public override IEnumerator OnOtherCardDie(PlayableCard card, CardSlot deathSlot, bool fromCombat, PlayableCard killer) { yield return ((AbilityBehaviour)this).PreSuccessfulTriggerSequence(); if (!((Object)(object)((AbilityBehaviour)this).Card == (Object)null) && !((AbilityBehaviour)this).Card.Dead) { int count = GetKillCount(((AbilityBehaviour)this).Card); KillCounts[((AbilityBehaviour)this).Card] = count + 1; yield return ((AbilityBehaviour)this).LearnAbility(0.25f); } } public static void Clear(PlayableCard card) { if (!((Object)(object)card == (Object)null)) { KillCounts.Remove(card); } } } [HarmonyPatch(typeof(CombatPhaseManager), "SlotAttackSlot")] public static class CrimsonRushPatch { private static readonly HashSet InternalAttack = new HashSet(); private static void Prefix(CardSlot attackingSlot, ref CardSlot opposingSlot, float waitAfter) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)attackingSlot == (Object)null) { return; } PlayableCard card = attackingSlot.Card; if ((Object)(object)card == (Object)null || !card.HasAbility(CrimsonRushAPI.ability.Id)) { return; } List list = ((!attackingSlot.IsPlayerSlot) ? Singleton.Instance.PlayerSlotsCopy : Singleton.Instance.OpponentSlotsCopy); foreach (CardSlot item in list) { if ((Object)(object)item == (Object)null || (Object)(object)item.Card == (Object)null || item.Card.Dead) { continue; } opposingSlot = item; break; } } private static void Postfix(CardSlot attackingSlot, CardSlot opposingSlot, float waitAfter, ref IEnumerator __result) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)attackingSlot == (Object)null) { return; } PlayableCard card = attackingSlot.Card; if (!((Object)(object)card == (Object)null) && card.HasAbility(CrimsonRushAPI.ability.Id) && !card.Dead) { int killCount = CrimsonRushBehaviour.GetKillCount(card); if (killCount > 0) { IEnumerator original = __result; __result = CrimsonRushAttackRoutine(original, card, attackingSlot, killCount); } } } private static IEnumerator CrimsonRushAttackRoutine(IEnumerator original, PlayableCard attackingCard, CardSlot attackingSlot, int killCount) { yield return original; if ((Object)(object)attackingCard == (Object)null || attackingCard.Dead || (Object)(object)attackingCard.Slot == (Object)null) { yield break; } CombatPhaseManager combat = Singleton.Instance; if ((Object)(object)combat == (Object)null) { yield break; } int remaining = killCount; while (remaining > 0) { CardSlot target = FindEnemyCreature(attackingSlot); if ((Object)(object)target == (Object)null) { break; } InternalAttack.Add(attackingCard); yield return combat.SlotAttackSlot(attackingSlot, target, 0f); InternalAttack.Remove(attackingCard); remaining--; if ((Object)(object)attackingCard == (Object)null || attackingCard.Dead || (Object)(object)attackingCard.Slot == (Object)null) { break; } } } private static CardSlot FindEnemyCreature(CardSlot attackingSlot) { if ((Object)(object)attackingSlot == (Object)null) { return null; } List list = ((!attackingSlot.IsPlayerSlot) ? Singleton.Instance.PlayerSlotsCopy : Singleton.Instance.OpponentSlotsCopy); foreach (CardSlot item in list) { if ((Object)(object)item == (Object)null || (Object)(object)item.Card == (Object)null || item.Card.Dead) { continue; } return item; } return null; } } [BepInPlugin("OLD_SA.CrimsonRush", "OLD SA Crimson Rush", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "OLD_SA.CrimsonRush"; public const string PluginName = "OLD SA Crimson Rush"; public const string PluginVersion = "1.0.0"; private void Awake() { Debug.Log((object)"[OLD SA Crimson Rush] Plugin loaded."); try { CrimsonRushAPI.Init(); Debug.Log((object)"[OLD SA Crimson Rush] Crimson Rush registered."); } catch (Exception ex) { Debug.LogError((object)"[OLD SA Crimson Rush] Failed to initialize:"); Debug.LogError((object)ex); } } }