Decompiled source of W and W Inc v0.1.145
plugins/WwInc.Plugin.dll
Decompiled 7 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.Versioning; using System.Text; using BepInEx; using Conductor.Data.Registers; using Conductor.Interfaces; using Conductor.RoomModifiers; using HarmonyLib; using Microsoft.CodeAnalysis; using Microsoft.Extensions.Configuration; using TrainworksReloaded.Base; using TrainworksReloaded.Core; using TrainworksReloaded.Core.Extensions; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("WwInc.Plugin")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.145.0")] [assembly: AssemblyInformationalVersion("0.1.145+2792d02beb20a9a1adfbd21b3bf4aca85116947c")] [assembly: AssemblyProduct("WwInc.Plugin")] [assembly: AssemblyTitle("WwInc.Plugin")] [assembly: AssemblyVersion("0.1.145.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace WwInc { public abstract class AcademicEffectBase : CardEffectBase { public override bool CanApplyInPreviewMode => false; public override PropDescriptions CreateEditorInspectorDescriptions() { return PropDescriptions.DisplayNone; } } public sealed class CardEffectAcademicTransfer : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { return p.targets.Count > 0; } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { AcademicRuntime.Core = m; CharacterState target = p.targets[0]; string paramStr = s.GetParamStr(); if (paramStr == "weakness") { List<CharacterState> list = new List<CharacterState>(); m.GetHeroManager().AddCharactersToList(list); int num = list.Sum((CharacterState u) => u.GetStatusEffectStacks("spell weakness")); foreach (CharacterState item in list) { item.RemoveStatusEffect("spell weakness", item.GetStatusEffectStacks("spell weakness"), false); } target.AddStatusEffect("spell weakness", num, (CharacterState)null, false, false); yield break; } if (paramStr == "debuffs") { foreach (CharacterState item2 in from u in AcademicRuntime.Units(target.GetCurrentRoomIndex(), (Type)2) where (Object)(object)u != (Object)(object)target select u) { TransferDebuffs(item2, target); } yield break; } throw new InvalidOperationException("Unknown academic transfer: " + paramStr); } internal static void TransferDebuffs(CharacterState source, CharacterState target) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 List<StatusEffectStack> list = new List<StatusEffectStack>(); source.GetStatusEffects(ref list, false); foreach (StatusEffectStack item in list) { item.State.GetSourceStatusEffectData(); if ((int)item.State.GetDisplayCategory() == 1) { int count = item.Count; string statusId = item.State.GetStatusId(); source.RemoveStatusEffect(statusId, count, false); target.AddStatusEffect(statusId, count, (CharacterState)null, false, false); } } } } public sealed class CardEffectAcademicHealthExchange : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { AcademicRuntime.Core = m; return AcademicRuntime.Units(p.selectedRoom, (Type)2).Count >= 2; } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { AcademicRuntime.Core = m; List<CharacterState> list = AcademicRuntime.Units(p.selectedRoom, (Type)2); if (list.Count >= 2) { CharacterState val = list[0]; CharacterState val2 = list[list.Count - 1]; int hP = val.GetHP(); int hP2 = val2.GetHP(); val.SetHealth(Math.Min(hP2, val.GetMaxHP()), val.GetMaxHP()); val2.SetHealth(Math.Min(hP, val2.GetMaxHP()), val2.GetMaxHP()); if (hP2 > val.GetMaxHP()) { val.AddStatusEffect("armor", hP2 - val.GetMaxHP(), (CharacterState)null, true, false); } if (hP > val2.GetMaxHP()) { val2.AddStatusEffect("armor", hP - val2.GetMaxHP(), (CharacterState)null, true, false); } } yield break; } } public sealed class CardEffectAcademicDeskSwap : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { AcademicRuntime.Core = m; return AcademicRuntime.Units(p.selectedRoom, (Type)2).Count >= 2; } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { AcademicRuntime.Core = m; List<CharacterState> list = AcademicRuntime.Units(p.selectedRoom, (Type)2); if (list.Count >= 2) { CharacterState val = list[list.Count - 1]; RoomState selectedRoom = p.GetSelectedRoom(m.GetRoomManager()); selectedRoom.RearrangeCharacter((Type)2, 0, list.Count - 1); selectedRoom.RearrangeCharacter((Type)2, list.Count - 2, 0); selectedRoom.UpdateSpawnPointPositions((Type)2, -1, false, true); yield return m.GetCombatManager().RunUnitTurn(val, (ICharacterManager)(object)m.GetMonsterManager(), (ICharacterManager)(object)m.GetHeroManager(), selectedRoom.GetRoomIndex(), false, (List<CharacterState>)null, true, (Action<int>)null, false); } } } public sealed class CardEffectAcademicSabbatical : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { return p.targets.Any((CharacterState u) => !u.HasStatusEffect("untouchable")); } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { AcademicRuntime.Core = m; foreach (CharacterState unit in p.targets) { if (!unit.HasStatusEffect("untouchable")) { unit.AddStatusEffect("untouchable", 1, (CharacterState)null, true, false); AcademicRuntime.NextTurnActions.Add(() => Wake(unit, p.playedCard, s.GetParamInt())); } } yield break; } private static IEnumerator Wake(CharacterState unit, CardState? card, int extra) { if (!unit.IsDestroyed && !unit.IsDead) { unit.RemoveStatusEffect("untouchable", 1, false); yield return unit.ApplyHeal(Math.Max(0, unit.GetMaxHP() - unit.GetHP()) / 2 + extra, true, card, (RelicState)null, false, (VfxAtLoc)null, 0); } } } public sealed class CardEffectAcademicArmorHonors : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { AcademicRuntime.Core = m; foreach (CharacterState unit in p.targets) { int attackDamage = unit.GetAttackDamage(); unit.AddStatusEffect("armor", attackDamage, (CharacterState)null, true, false); AcademicRuntime.ZeroAttack.Add(unit); unit.AddStatusEffect("dazed", 1, (CharacterState)null, true, false); AcademicRuntime.EndTurnActions.Add(delegate { if (!unit.IsDestroyed) { AcademicRuntime.ZeroAttack.Remove(unit); } }); } yield break; } } public sealed class CardEffectAcademicConversion : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { AcademicRuntime.Core = m; CharacterState val = p.characterThatActivatedAbility ?? p.selfTarget; if ((Object)(object)val != (Object)null) { AcademicRuntime.HealingModes[val] = s.GetParamInt(); } yield break; } } public sealed class CardEffectAcademicConsumeCredits : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { return m.GetCardManager().GetHand(false).Any((CardState c) => c != p.playedCard && (int)c.GetCardType() == 0); } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { if (m.GetSaveManager().PreviewMode) { yield break; } AcademicRuntime.Core = m; CharacterState unit = p.characterThatActivatedAbility ?? p.selfTarget; if (!((Object)(object)unit == (Object)null)) { yield return AcademicRuntime.ChooseHand(p.playedCard, (CardState c) => (int)c.GetCardType() == 0, (CardState chosen) => ResolveCredits(chosen, unit, m)); } } private static IEnumerator ResolveCredits(CardState chosen, CharacterState unit, ICoreGameManagers m) { AcademicRuntime.Core = m; int conduit = Math.Max(0, chosen.GetCostWithoutAnyModifications()) * 5; yield return m.GetCardManager().ConsumeCardWithoutPlaying(new DiscardCardParams { discardCard = chosen, overrideDiscardEffect = (DiscardEffect)2 }); unit.AddStatusEffect("conduit", conduit, (CharacterState)null, true, false); } } public sealed class CardEffectAcademicConduitTransfer : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { return m.GetCardManager().GetHand(false).Any((CardState c) => c != p.playedCard && (int)c.GetCardType() == 0); } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { if (m.GetSaveManager().PreviewMode) { yield break; } AcademicRuntime.Core = m; yield return AcademicRuntime.ChooseHand(p.playedCard, (CardState c) => (int)c.GetCardType() == 0, delegate(CardState chosen) { AcademicRuntime.Core = m; int num = 0; foreach (CharacterState item in AcademicRuntime.AllAllies()) { int statusEffectStacks = item.GetStatusEffectStacks("conduit"); num += statusEffectStacks; item.RemoveStatusEffect("conduit", statusEffectStacks, false); } AcademicRuntime.ModifyCard(chosen, num, 0, thisTurn: false); SpellRules.Explosive(chosen); }); } } public sealed class CardEffectAcademicEquipmentReturn : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { AcademicRuntime.Core = m; foreach (CharacterState unit in p.targets) { CardState equipment = unit.GetEquipment().FirstOrDefault(); if (equipment == null) { continue; } bool preview = m.GetSaveManager().PreviewMode; if (!preview) { equipment.SetRemoveFromStandByPileOverride((CardPile)3); } if (preview) { AcademicRuntime.EquipmentPreviewDepth++; } try { yield return unit.RemoveEquipment(m, equipment); } finally { if (preview) { AcademicRuntime.EquipmentPreviewDepth--; } } if (!preview) { AcademicRuntime.SetFixedCost(equipment, 0, thisTurn: true); } unit.AddStatusEffect("damage shield", 1, (CharacterState)null, true, false); } } } public sealed class CardEffectAcademicOneTurnUpgrade : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { AcademicRuntime.Core = m; foreach (CharacterState unit in p.targets) { CardUpgradeState upgrade = new CardUpgradeState(); upgrade.Setup(s.GetParamCardUpgradeData(), false, false); yield return unit.ApplyCardUpgrade(upgrade, false, "", true, false, (CardState)null, (Action<UpgradeApplicationResult>)null, (TrainRoomAttachmentState)null, false); AcademicRuntime.NextTurnActions.Add(() => Remove(unit, upgrade)); } } private static IEnumerator Remove(CharacterState unit, CardUpgradeState upgrade) { if (!unit.IsDestroyed) { yield return unit.RemoveCardUpgrade(upgrade, "", true, (TrainRoomAttachmentState)null); } } } internal static class AcademicMath { internal static int CreditDamageIncrement(long current, int amount) { return (int)Math.Max(0L, Math.Min(Math.Max(0, amount), int.MaxValue - Math.Max(0L, current))); } internal static int OverdamageAmount(int damage, int sustained) { return (int)Math.Min(2147483647L, Math.Max(0L, (long)damage - (long)Math.Max(0, sustained))); } internal static int ScaleOverdamage(int excess, int percent) { return (int)Math.Min(2147483647L, (long)Math.Max(0, excess) * (long)Math.Max(0, percent) / 100); } internal static int SharedHealing(int damage, int allies) { if (allies <= 0) { return 0; } return Math.Max(0, damage) / allies; } internal static int ExcessHealing(int healing, int health, int maximum) { if (healing < 9999) { return (int)Math.Max(0L, Math.Min(2147483647L, Math.Max(0, healing) - Math.Max(0L, (long)maximum - (long)health))); } return 0; } internal static int OverhealArmor(int excess, int maximum) { return Math.Min(Math.Max(0, excess), Math.Max(0, maximum)); } internal static int ConsumedDamage(int incoming, int perCard, int count) { return (int)Math.Max(0L, Math.Min(2147483647L, incoming + (long)Math.Max(0, perCard) * (long)Math.Max(0, count))); } internal static (int count, bool refund) RefundProgress(int count, int kills) { if (kills <= 0) { return (count: count, refund: false); } if (count < 4) { return (count: count + 1, refund: false); } return (count: 0, refund: true); } internal static int EducationPower(int attack, int educators) { return (int)Math.Min(2147483647L, (long)(Math.Max(0, attack) / 2) * (long)Math.Max(0, educators)); } internal static bool FirstQualifyingSpell(HashSet<string> used, string kind, int floor, int amount) { if (amount > 0) { return used.Add(kind + ":" + floor); } return false; } internal static int EffectiveX(int paid, int modifier) { return (int)Math.Max(0L, Math.Min(2147483647L, (long)paid + (long)modifier)); } internal static int ChampionRank(IEnumerable<string> upgrades, string prefix) { int num = 0; foreach (string upgrade in upgrades) { for (int i = 1; i <= 3; i++) { if (upgrade.EndsWith(prefix + i, StringComparison.Ordinal)) { num = Math.Max(num, i); } } } return num; } internal static int ChampionAura(int rank, int allies, int perMage = 5) { return (int)Math.Min(2147483647L, (long)Math.Max(0, rank) * (long)Math.Max(0, perMage) * Math.Max(0, allies)); } internal static (int attack, int health) ServingStats(long conduit) { int num = (int)Math.Max(0L, Math.Min(2147483646L, conduit)); return (attack: num, health: num + 1); } internal static bool Mixed(int left, int right) { if ((left & 1) == 0 || (right & 2) == 0) { if ((left & 2) != 0) { return (right & 1) != 0; } return false; } return true; } internal static bool CanInsertChaperone(int count) { return count < 7; } internal static (int discounts, int remainder) Tuition(int previous, int actualDamage) { long num = (long)Math.Max(0, previous) + (long)Math.Max(0, actualDamage); return (discounts: (int)(num / 30), remainder: (int)(num % 30)); } internal static int RedirectionDamage(int previousDazed) { return checked(Math.Max(0, previousDazed) * 10); } } internal static class AcademicRuntime { internal sealed class SpellResolution { internal CardState Card; internal int Floor; internal bool FirstDamage; internal bool WasFrozen; internal bool Redirected; internal bool Indirect; internal readonly HashSet<string> Rules = new HashSet<string>(); internal readonly List<Action> Cleanup = new List<Action>(); internal CharacterState? Target; internal CharacterState? EnemyBehind; internal readonly Dictionary<int, int> Damage = new Dictionary<int, int>(); internal readonly Dictionary<int, int> Healing = new Dictionary<int, int>(); internal readonly Dictionary<int, int> Kills = new Dictionary<int, int>(); } internal static ICoreGameManagers Core = null; internal static int Turn; internal static Trigger ArcaneSlay; internal static int ConversionDepth; internal static int HostileHealingDepth; internal static int EquipmentPreviewDepth; internal static CardState? LastPlayedCommonSpell; internal static readonly Dictionary<CharacterState, int> HealingModes = new Dictionary<CharacterState, int>(); internal static readonly Dictionary<CharacterState, int> DamageCredits = new Dictionary<CharacterState, int>(); internal static readonly List<Action> EndTurnActions = new List<Action>(); internal static readonly List<Func<IEnumerator>> NextTurnActions = new List<Func<IEnumerator>>(); internal static readonly Stack<SpellResolution> Frames = new Stack<SpellResolution>(); internal static bool DamageSpellPlayed; internal static CardState? FirstDamageSpell; internal static readonly HashSet<CharacterState> ZeroAttack = new HashSet<CharacterState>(); internal static readonly Dictionary<CharacterState, List<CardState>> BoundForAttack = new Dictionary<CharacterState, List<CardState>>(); internal static readonly Dictionary<CardState, int> FixedCosts = new Dictionary<CardState, int>(); internal static bool Simulating { get { if (Core != null) { return Core.GetSaveManager().PreviewMode; } return false; } } internal static bool Active { get { if (Core != null) { if (Simulating) { return PreviewScope.Active; } return true; } return false; } } internal static string Id(CardState? card) { return ((card != null) ? card.GetAssetName() : null) ?? ""; } internal static bool Is(CharacterState unit, string id) { return ((Object)unit.GetSourceCharacterData()).name.EndsWith(id + "_Character", StringComparison.Ordinal); } internal static List<CharacterState> Units(int floor, Type team = (Type)2) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) List<CharacterState> list = new List<CharacterState>(); RoomState room = Core.GetRoomManager().GetRoom(floor); if ((Object)(object)room != (Object)null) { room.AddCharactersToList(list, team, false, true); } return list.Where((CharacterState c) => !c.IsDead && !c.IsDestroyed).ToList(); } internal static IEnumerable<CharacterState> AllAllies() { List<CharacterState> list = new List<CharacterState>(); Core.GetMonsterManager().AddCharactersToList(list); return list.Where((CharacterState u) => !u.IsDead && !u.IsDestroyed); } internal static void Reset(CardManager manager) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) Core = ((AllGameManagers)AccessTools.Field(typeof(CardManager), "allGameManagers").GetValue(manager)).GetCoreManagers(); SocialRules.AuraBonuses.Clear(); ZeroAttack.Clear(); FixedCosts.Clear(); BoundForAttack.Clear(); Turn = 0; ConversionDepth = 0; HostileHealingDepth = 0; EquipmentPreviewDepth = 0; Frames.Clear(); LastPlayedCommonSpell = null; HealingModes.Clear(); SpellRules.Reset(); MineMineMine.Claimed.Clear(); DamageCredits.Clear(); EndTurnActions.Clear(); NextTurnActions.Clear(); DamageSpellPlayed = false; FirstDamageSpell = null; CardEffectAcademicPurgePermit.BeginBattle(Core); } internal static IEnumerator BeginTurn() { if (Core != null && !Core.GetSaveManager().PreviewMode) { Turn++; DamageSpellPlayed = false; FirstDamageSpell = null; HealingModes.Clear(); Func<IEnumerator>[] array = NextTurnActions.ToArray(); NextTurnActions.Clear(); Func<IEnumerator>[] array2 = array; foreach (Func<IEnumerator> func in array2) { yield return func(); } yield return SpellRules.BeginTurn(); yield return SocialRules.BeginTurn(); SocialRules.RefreshAuras(); yield return CateringRules.BeginTurn(); } } internal static void EndTurn() { if (Active) { if (!DamageSpellPlayed && SpellRules.HasRelic("WW_A04")) { Core.GetCardManager().AdjustDrawCountModifier(1, (CardState)null, (Action<CardState>)null); } TurnCleanup.Run(EndTurnActions); HealingModes.Clear(); SpellRules.Pending.RemoveAll((SpellRules.Rule r) => r.Kind == "power"); } } internal static void RecordDamage(CharacterState target, int lost, bool died, CardState? card, CharacterState? attacker, int floor) { //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Invalid comparison between Unknown and I4 if (!Active || ConversionDepth != 0) { return; } if (!Simulating && lost > 0 && (Object)(object)attacker != (Object)null && Is(attacker, "WW_U18")) { int value; (int, int) tuple = AcademicMath.Tuition(DamageCredits.TryGetValue(attacker, out value) ? value : 0, lost); var (num, _) = tuple; DamageCredits[attacker] = tuple.Item2; if (num > 0) { CardState[] array = (from c in Core.GetCardManager().GetHand(false) where c.HasTrait(typeof(CardTraitFreeze)) select c).ToArray(); for (int num2 = 0; num2 < array.Length; num2++) { ModifyCard(array[num2], 0, num, thisTurn: false); } } } if (Frames.Count == 0 || card == null || Frames.Peek().Card != card) { return; } SpellResolution spellResolution = Frames.Peek(); if ((int)target.GetTeamType() == 1) { spellResolution.Damage[floor] = (spellResolution.Damage.TryGetValue(floor, out var value2) ? (value2 + lost) : lost); if (died) { spellResolution.Kills[floor] = ((!spellResolution.Kills.TryGetValue(floor, out value2)) ? 1 : (value2 + 1)); } } } internal static void RecordHeal(CharacterState target, int restored, int excess, CardState? source) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 if (Active && ConversionDepth == 0 && Frames.Count != 0 && source != null && Frames.Peek().Card == source && (int)target.GetTeamType() == 2) { int currentRoomIndex = target.GetCurrentRoomIndex(); SpellResolution spellResolution = Frames.Peek(); spellResolution.Healing[currentRoomIndex] = (spellResolution.Healing.TryGetValue(currentRoomIndex, out var value) ? (value + restored) : restored); } } internal static IEnumerator AfterSpell(SpellResolution frame) { yield return SpellRules.After(frame); if (frame.FirstDamage) { int amount = frame.Damage.Values.Sum(); foreach (CharacterState unit in from u in AllAllies() where Is(u, "WW_U17") select u) { unit.SetAttackDamage(unit.GetAttackDamageWithoutStatusEffectBuffs() + amount); EndTurnActions.Add(delegate { if (!unit.IsDestroyed) { unit.SetAttackDamage(Math.Max(0, unit.GetAttackDamageWithoutStatusEffectBuffs() - amount)); } }); } } foreach (KeyValuePair<int, int> kill in frame.Kills) { if (kill.Value > 0) { yield return ArcaneSlayEvent.Dispatch(frame.Card, kill.Key, kill.Value); } } ConversionDepth++; try { if (frame.Indirect) { yield break; } foreach (KeyValuePair<int, int> pair in frame.Damage) { if (AcademicMath.FirstQualifyingSpell(SpellRules.OnceTurn, "U02Damage", pair.Key, pair.Value)) { CharacterState[] array = (from u in Units(pair.Key, (Type)2) where Is(u, "WW_U02") select u).ToArray(); for (int num = 0; num < array.Length; num++) { _ = array[num]; yield return HealShared(pair.Key, pair.Value, frame.Card); } } } } finally { ConversionDepth--; } } internal static IEnumerator HealShared(int floor, int amount, CardState? source) { CharacterState[] array = Units(floor, (Type)2).ToArray(); int healing = AcademicMath.SharedHealing(amount, array.Length); if (healing <= 0) { yield break; } CharacterState[] array2 = array; foreach (CharacterState val in array2) { if (!val.IsDestroyed && val.IsAlive) { yield return val.ApplyHeal(healing, true, source, (RelicState)null, false, (VfxAtLoc)null, 0); } } } internal static CardUpgradeState ModifyCard(CardState card, int power, int discount, bool thisTurn) { if (FixedCosts.TryGetValue(card, out var value) && discount != 0) { FixedCosts[card] = Math.Max(0, value - discount); } CardUpgradeState upgrade = PowerUpgrade(power, card.GetMagicPowerMultiplierFromTraits()); upgrade.SetCostReduction(discount); CardStateModifiers mods = card.GetTemporaryCardStateModifiers(); mods.AddUpgrade(upgrade, (CardStateModifiers)null); card.UpdateCardBodyText((SaveManager)null); if (thisTurn) { EndTurnActions.Add(delegate { mods.RemoveUpgrade(upgrade); if (FixedCosts.TryGetValue(card, out var value2)) { FixedCosts[card] = Math.Max(0, value2 + discount); } card.UpdateCardBodyText((SaveManager)null); }); } return upgrade; } internal static CardUpgradeState PowerUpgrade(int power, int multiplier = 1) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown CardUpgradeState val = new CardUpgradeState(); val.Setup(); if (power != 0) { CardUpgradeData val2 = ScriptableObject.CreateInstance<CardUpgradeData>(); AccessTools.Field(typeof(CardUpgradeData), "bonusDamage").SetValue(val2, power); AccessTools.Field(typeof(CardUpgradeData), "bonusHeal").SetValue(val2, power); AccessTools.Field(typeof(CardUpgradeState), "sourceCardUpgradeData").SetValue(val, val2); } val.SetAttackDamage(power * multiplier); val.SetAdditionalHeal(power * multiplier); return val; } internal static void SetFixedCost(CardState card, int cost, bool thisTurn) { int old; bool previous = FixedCosts.TryGetValue(card, out old); FixedCosts[card] = cost; if (thisTurn) { EndTurnActions.Add(delegate { if (previous) { FixedCosts[card] = old; } else { FixedCosts.Remove(card); } card.UpdateCardBodyText((SaveManager)null); }); } card.UpdateCardBodyText((SaveManager)null); } internal static void Trait(CardState card, string type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown CardTraitData val = new CardTraitData(); val.Setup(type); Core.GetCardManager().AddTemporaryTraitToCard(card, val, true, false, true); } internal static IEnumerator ChooseHand(CardState? source, Func<CardState, bool> eligible, Action<CardState> picked) { return ChooseHand(source, eligible, (CardState c) => Complete(c, picked)); } internal static IEnumerator ChooseHand(CardState? source, Func<CardState, bool> eligible, Func<CardState, IEnumerator> apply) { CardManager cardManager = Core.GetCardManager(); if (cardManager.GetHand(false).Any((CardState c) => c != source && eligible(c))) { yield return cardManager.SelectCardFromHand(new Params { descriptionKey = "david.wwinc.ChooseCard", filterCallback = (FilterCardStateDelegate)((CardState c) => c == source || !eligible(c)), cardChosenCallback = (CardStateChosenDelegate)((CardState c, CardManager m) => ApplyChoice(c, source, eligible, apply, m)), disableIneligibleCards = true }, false); } } private static IEnumerator ApplyChoice(CardState card, CardState? source, Func<CardState, bool> eligible, Func<CardState, IEnumerator> apply, CardManager manager) { if (card != source && manager.GetHand(false).Contains(card) && eligible(card)) { yield return apply(card); } } private static IEnumerator Complete(CardState card, Action<CardState> picked) { picked(card); yield break; } } internal static class AcademicTooltips { private static readonly HashSet<string> Cards = new HashSet<string>((from i in Enumerable.Range(1, 32) select "WW_S" + i.ToString("00")).Concat(new string[19] { "WW_C01", "WW_C02", "WW_E01", "WW_E02", "WW_R01", "WW_R02", "WW_U01", "WW_U02", "WW_U03", "WW_U04", "WW_U05", "WW_U06", "WW_U08", "WW_U10", "WW_U11", "WW_U13", "WW_U16", "WW_U17", "WW_U18" })); internal static bool TryCreate(CardState? card, CharacterState? unit, out TooltipContent content) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) content = default(TooltipContent); if (card == null) { return false; } string asset = AcademicRuntime.Id(card); if (!Cards.Any((string id) => asset.EndsWith(id, StringComparison.Ordinal))) { return false; } string overrideDescriptionKey = card.GetOverrideDescriptionKey(); if (string.IsNullOrWhiteSpace(overrideDescriptionKey) || !LocalizationExtensions.HasTranslation(overrideDescriptionKey)) { return false; } string text = LocalizationExtensions.Localize(overrideDescriptionKey, (ILocalizationParameterContext)new CardEffectLocalizationContext((ILocalizationEffectPower)(object)card, unit, (CardState)null, (IRoomStateModifier)null, (CharacterStatusEffectAdjustments)null)); if (string.IsNullOrWhiteSpace(text)) { return false; } content = new TooltipContent(card.GetTitle(), text, (TooltipDesignType)8, "david.wwinc.effect." + asset, false, false); return true; } internal static bool Reserved(CharacterState unit, out TooltipContent content) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) content = default(TooltipContent); List<string> list = new List<string>(); if (SpellRules.Archived.TryGetValue(unit, out List<CardState> value)) { CardState[] array = value.ToArray(); foreach (CardState val in array) { list.Add(val.GetTitle()); } } if (list.Count == 0) { return false; } string text = ((list.Count == 0) ? LocalizationExtensions.Localize("david.wwinc.ReservedSpellsEmpty", (ILocalizationParameterContext)null) : string.Join("<br>", list)); content = new TooltipContent(LocalizationExtensions.Localize("david.wwinc.ReservedSpellsTitle", (ILocalizationParameterContext)null), text, (TooltipDesignType)8, "david.wwinc.reserved", false, false); return true; } internal static IEnumerable<(TooltipContent content, bool allowDuplicates)> Append(IEnumerable<(TooltipContent content, bool allowDuplicates)> original, CharacterState unit) { HashSet<string> seen = new HashSet<string>(); foreach (var item in original) { seen.Add(item.content.tooltipId); yield return item; } if (TryCreate(unit.GetSpawnerCard(), unit, out var content) && seen.Add(content.tooltipId)) { yield return (content: content, allowDuplicates: false); } if (Reserved(unit, out var content2) && seen.Add(content2.tooltipId)) { yield return (content: content2, allowDuplicates: false); } } } [HarmonyPatch(typeof(CardTooltipContainer), "AddTooltipsForCardState")] internal static class AcademicCardTooltipHook { private static void Postfix(CardTooltipContainer __instance, CardState cardState) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (AcademicTooltips.TryCreate(cardState, null, out var content)) { TooltipUI obj = ((TooltipContainer)__instance).InstantiateTooltip(content.tooltipId, content.designType, false, false, false); if (obj != null) { obj.Set(content.title, content.body, false); } } } } [HarmonyPatch(typeof(CharacterTooltipHelper), "GetAdditionalTooltipContents")] internal static class AcademicCharacterTooltipHook { private static void Postfix(CharacterState characterState, ref IEnumerable<(TooltipContent content, bool allowDuplicates)> __result) { __result = AcademicTooltips.Append(__result, characterState); } } public sealed class CardEffectAcademicTome : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; private static bool Eligible(CardState card, CardEffectState effect, ICoreGameManagers managers) { CardUpgradeData paramCardUpgradeData = effect.GetParamCardUpgradeData(); if (paramCardUpgradeData != null) { return paramCardUpgradeData.GetFilters().All((CardUpgradeMaskData filter) => filter.FilterCard<CardState>(card, managers.GetRelicManager())); } return false; } public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { return m.GetCardManager().GetHand(false).Any((CardState c) => c != p.playedCard && Eligible(c, s, m)); } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { if (!m.GetSaveManager().PreviewMode) { AcademicRuntime.Core = m; yield return AcademicRuntime.ChooseHand(p.playedCard, (CardState c) => Eligible(c, s, m), delegate(CardState selected) { CardEffectAddTempCardUpgradeToCardsInHand.TryApplyUpgradeToCard(selected, false, s, p, m); }); } } } public sealed class CardEffectAcademicReturnFrozen : AcademicEffectBase { public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { return p.playedCard != null; } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { if (!m.GetSaveManager().PreviewMode && p.playedCard != null) { SpellRules.AddRule(p.playedCard, "return_frozen"); } yield break; } internal static void ProtectUntilNextTurn(CardState card, CardManager manager) { if (!card.HasTrait(typeof(CardTraitFreeze))) { AcademicRuntime.Trait(card, "CardTraitFreeze"); } if (!card.HasTrait(typeof(CardTraitUnplayable))) { AcademicRuntime.Trait(card, "CardTraitUnplayable"); CardTraitState added = card.GetTemporaryCardStateModifiers().GetTemporaryTraits().Last((CardTraitState t) => t is CardTraitUnplayable); AcademicRuntime.NextTurnActions.Add(() => Unlock(card, added, manager)); } } private static IEnumerator Unlock(CardState card, CardTraitState added, CardManager manager) { card.RemoveTemporaryTrait(added); card.UpdateCardBodyText((SaveManager)null); if (manager.GetHand(false).Contains(card)) { manager.RefreshCardInHand(card, true, false, false); } yield break; } } internal static class ArcaneSlayEvent { internal sealed class Data : FireTriggersData { internal CardState Source; } private sealed class Context { internal CharacterState Unit; internal CardState Source; } private static readonly Stack<CardState> enqueuing = new Stack<CardState>(); private static readonly Stack<Context> executing = new Stack<Context>(); internal static CardState? EnqueuingSource { get { if (enqueuing.Count <= 0) { return null; } return enqueuing.Peek(); } } internal static IEnumerator Dispatch(CardState source, int floor, int kills) { enqueuing.Push(source); try { yield return AcademicRuntime.Core.GetCombatManager().ApplyCharacterEffectsForRoom(AcademicRuntime.ArcaneSlay, floor, true, kills, (CharacterState)null); } finally { enqueuing.Pop(); } } internal static IEnumerator Run(IEnumerator original, CharacterState unit, Data data) { executing.Push(new Context { Unit = unit, Source = data.Source }); try { yield return original; } finally { executing.Pop(); } } internal static CardState? Source(CardEffectParams p) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (executing.Count > 0 && (Object)(object)executing.Peek().Unit == (Object)(object)p.selfTarget) { CharacterTriggerState sourceCharacterTriggerState = p.sourceCharacterTriggerState; if (((sourceCharacterTriggerState != null) ? new Trigger?(sourceCharacterTriggerState.GetTrigger()) : ((Trigger?)null)) == (Trigger?)AcademicRuntime.ArcaneSlay) { return executing.Peek().Source; } } return null; } } [HarmonyPatch(typeof(CombatManager), "QueueTrigger", new Type[] { typeof(CharacterState), typeof(Trigger), typeof(CharacterState), typeof(bool), typeof(bool), typeof(FireTriggersData), typeof(int), typeof(CharacterTriggerState) })] internal static class ArcaneSlayQueueHook { private static void Prefix(Trigger trigger, ref FireTriggersData fireTriggersData) { //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) if (trigger == AcademicRuntime.ArcaneSlay && fireTriggersData == null) { CardState enqueuingSource = ArcaneSlayEvent.EnqueuingSource; if (enqueuingSource != null) { fireTriggersData = (FireTriggersData)(object)new ArcaneSlayEvent.Data { Source = enqueuingSource }; } } } } [HarmonyPatch(typeof(CharacterState), "FireTriggers")] internal static class ArcaneSlayTriggerHook { private static void Postfix(CharacterState __instance, Trigger trigger, FireTriggersData fireTriggersData, ref IEnumerator __result) { //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) if (trigger == AcademicRuntime.ArcaneSlay && fireTriggersData is ArcaneSlayEvent.Data data) { __result = ArcaneSlayEvent.Run(__result, __instance, data); } } } public sealed class CardEffectAcademicUpgradeSlayingSpell : AcademicEffectBase { public override bool CanPlayAfterBossDead => true; public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { return true; } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { if (!m.GetSaveManager().PreviewMode && !AcademicRuntime.Simulating) { CardState val = ArcaneSlayEvent.Source(p); if (val != null && (int)val.GetCardType() == 0 && !val.IsAnyAbility()) { CardUpgradeState val2 = default(CardUpgradeState); CardUpgradeHelper.TryApplyUpgradeToCard(val, (CardState)null, s.GetParamCardUpgradeData(), false, p.isFromHiddenTrigger, m, ref val2); val.UpdateCardBodyText((SaveManager)null); m.GetCardManager().RefreshCardInHand(val, true, false, false); } } yield break; } } internal static class CateringRules { internal static CharacterData Stand; internal static CharacterData Serving; internal static bool IsStand(CharacterState unit) { return ((Object)unit.GetSourceCharacterData()).name.EndsWith("WW_Token_IceCreamStand", StringComparison.Ordinal); } internal static bool CanSpawn(ICoreGameManagers core, int floor, SpawnPoint? location, int size) { RoomState room = core.GetRoomManager().GetRoom(floor); if ((Object)(object)room != (Object)null && !room.GetIsPyreRoom() && room.IsRoomEnabled() && !room.IsRoomSummonBlocked(core.GetRelicManager()) && !room.WillBeAtCapacity((Type)2, size)) { return core.GetMonsterManager().GetCanSpawnMonster(floor, location, size, false, false); } return false; } internal static IEnumerator BeginTurn() { if (!AcademicRuntime.Active || (Object)(object)Stand == (Object)null || (Object)(object)Serving == (Object)null) { yield break; } ICoreGameManagers core = AcademicRuntime.Core; SocialRules.RefreshAuras(); core.GetRoomManager().UpdateEnchantments(); foreach (int floor in SocialRules.FloorsBottomUp()) { CharacterState[] array = SocialRules.VisualUnits(floor).Where(IsStand).ToArray(); CharacterState[] array2 = array; foreach (CharacterState val in array2) { if (!val.IsDead && !val.IsDestroyed && val.GetCurrentRoomIndex() == floor && CanSpawn(core, floor, null, Serving.GetSize())) { long conduit = ((IEnumerable<CharacterState>)AcademicRuntime.Units(floor, (Type)2)).Sum((Func<CharacterState, long>)((CharacterState u) => Math.Max(0, u.GetStatusEffectStacks("conduit")))); (int attack, int health) stats = AcademicMath.ServingStats(conduit); CharacterState created = null; yield return core.GetMonsterManager().CreateMonsterState(Serving, (CardState)null, floor, (Action<CharacterState>)delegate(CharacterState u) { created = u; }, (SpawnMode)1, (SpawnPoint)null, (Action<CharacterState>)null, false, (CharacterData)null, (List<string>)null, (AddStatusEffectParams)null, true, (Action<CharacterState>)null, true, (CardState)null); if (!((Object)(object)created == (Object)null)) { CardUpgradeState val2 = new CardUpgradeState(); val2.Setup(); val2.SetAttackDamage(stats.attack); val2.SetAdditionalHP(stats.health - Serving.GetHealth()); yield return created.ApplyCardUpgrade(val2, false, "", true, false, (CardState)null, (Action<UpgradeApplicationResult>)null, (TrainRoomAttachmentState)null, false); } } } } } } public sealed class CardEffectAcademicCatering : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { int selectedRoom = p.selectedRoom; SpawnPoint dropLocation = p.dropLocation; CharacterData paramCharacterData = s.GetParamCharacterData(); return CateringRules.CanSpawn(m, selectedRoom, dropLocation, (paramCharacterData == null) ? 1 : paramCharacterData.GetSize()); } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { AcademicRuntime.Core = m; CharacterData paramCharacterData = s.GetParamCharacterData(); if (!((Object)(object)paramCharacterData == (Object)null) && CateringRules.CanSpawn(m, p.selectedRoom, p.dropLocation, paramCharacterData.GetSize())) { yield return m.GetMonsterManager().CreateMonsterState(paramCharacterData, (CardState)null, p.selectedRoom, (Action<CharacterState>)delegate { }, (SpawnMode)((p.dropLocation == null) ? 1 : 3), p.dropLocation, (Action<CharacterState>)null, false, (CharacterData)null, (List<string>)null, (AddStatusEffectParams)null, true, (Action<CharacterState>)null, true, p.playedCard); } } } internal static class ChampionPathText { private static readonly string[] Prefixes = new string[2] { "WW_FratBro", "WW_QueenBee" }; internal static IEnumerable<CardUpgradeState> Selected(CardState? card, CharacterState? unit = null) { if (card == null) { return Array.Empty<CardUpgradeState>(); } string text = AcademicRuntime.Id(card); if (!text.EndsWith("WW_C01", StringComparison.Ordinal) && !text.EndsWith("WW_C02", StringComparison.Ordinal)) { return Array.Empty<CardUpgradeState>(); } List<CardUpgradeState> list = new List<CardUpgradeState>(card.GetCardStateModifiers().GetCardUpgrades()); list.AddRange(card.GetTemporaryCardStateModifiers().GetCardUpgrades()); if ((Object)(object)unit != (Object)null) { list.AddRange(unit.GetAppliedCardUpgrades()); } List<CardUpgradeState> list2 = new List<CardUpgradeState>(); string[] prefixes = Prefixes; foreach (string prefix in prefixes) { int rank = AcademicMath.ChampionRank(list.Select((CardUpgradeState u) => u.GetAssetName()), prefix); if (rank != 0) { CardUpgradeState val = ((IEnumerable<CardUpgradeState>)list).FirstOrDefault((Func<CardUpgradeState, bool>)((CardUpgradeState u) => u.GetAssetName().EndsWith(prefix + rank, StringComparison.Ordinal))); if (val != null && (Object)(object)val.GetSourceCardUpgradeData() != (Object)null) { list2.Add(val); } } } return list2; } internal static string Description(CardUpgradeState upgrade, CardState card) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown return LocalizationExtensions.Localize(upgrade.GetUpgradeDescriptionKey(), (ILocalizationParameterContext)new CardEffectLocalizationContext((ILocalizationEffectPower)(object)upgrade.GetSourceCardUpgradeData(), (CharacterState)null, card, (IRoomStateModifier)null, (CharacterStatusEffectAdjustments)null)); } } [HarmonyPatch(typeof(CardState), "GenerateCardBodyText")] internal static class ChampionPathCardTextHook { private static void Postfix(CardState __instance, CharacterState associatedCharacterState, ref string generatedText) { foreach (CardUpgradeState item in ChampionPathText.Selected(__instance, associatedCharacterState)) { string text = ChampionPathText.Description(item, __instance); if (!string.IsNullOrWhiteSpace(text)) { generatedText = generatedText + (string.IsNullOrWhiteSpace(generatedText) ? "" : Environment.NewLine) + text; } } } } [HarmonyPatch(typeof(CharacterTooltipHelper), "GetAdditionalTooltipContents")] internal static class ChampionPathTooltipHook { private static void Postfix(CharacterState characterState, ref IEnumerable<(TooltipContent content, bool allowDuplicates)> __result) { __result = Append(__result, characterState); } private static IEnumerable<(TooltipContent content, bool allowDuplicates)> Append(IEnumerable<(TooltipContent content, bool allowDuplicates)> original, CharacterState unit) { HashSet<string> seen = new HashSet<string>(); foreach (var item in original) { seen.Add(item.content.tooltipId); yield return item; } CardState card = ((unit != null) ? unit.GetSpawnerCard() : null); foreach (CardUpgradeState item2 in ChampionPathText.Selected(card, unit)) { string text = "david.wwinc.path." + item2.GetAssetName(); if (seen.Add(text)) { yield return (content: new TooltipContent(item2.GetUpgradeTitle(), ChampionPathText.Description(item2, card), (TooltipDesignType)8, text, false, false), allowDuplicates: false); } } } } internal sealed class CollectionSnapshot { private readonly List<(FieldInfo field, object? value)> fields = new List<(FieldInfo, object)>(); internal CollectionSnapshot(params Type[] owners) { for (int i = 0; i < owners.Length; i++) { FieldInfo[] array = owners[i].GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in array) { if (!fieldInfo.IsLiteral) { fields.Add((fieldInfo, Clone(fieldInfo.GetValue(null)))); } } } } internal void Restore() { foreach (var field in fields) { if (!field.field.IsInitOnly) { field.field.SetValue(null, field.value); } else if (IsContainer(field.value)) { Fill(field.field.GetValue(null), field.value); } } } private static bool IsContainer(object? value) { if (value == null) { return false; } Type type = value.GetType(); if (type.IsGenericType) { return IEnumerableUtility.Contains<Type>((IReadOnlyList<Type>)new Type[4] { typeof(Dictionary<, >), typeof(List<>), typeof(HashSet<>), typeof(Stack<>) }, type.GetGenericTypeDefinition()); } return false; } private static object? Clone(object? value) { if (!IsContainer(value)) { return value; } object? obj = Activator.CreateInstance(value.GetType()); Fill(obj, value); return obj; } private static void Fill(object target, object source) { target.GetType().GetMethod("Clear").Invoke(target, null); if (target is IDictionary dictionary) { { foreach (DictionaryEntry item in (IDictionary)source) { dictionary.Add(item.Key, Clone(item.Value)); } return; } } IEnumerable<object> enumerable = ((IEnumerable)source).Cast<object>(); bool flag = target.GetType().GetGenericTypeDefinition() == typeof(Stack<>); if (flag) { enumerable = enumerable.Reverse(); } MethodInfo method = target.GetType().GetMethod(flag ? "Push" : "Add"); foreach (object item2 in enumerable) { method.Invoke(target, new object[1] { Clone(item2) }); } } } [HarmonyPatch(typeof(CardManager), "SetupCards")] internal static class BattleStartHook { private static void Postfix(CardManager __instance) { AcademicRuntime.Reset(__instance); } } [HarmonyPatch(typeof(CardManager), "DrawHand")] internal static class TurnStartHook { private static void Postfix(ref IEnumerator __result) { __result = Run(__result); } private static IEnumerator Run(IEnumerator original) { yield return AcademicRuntime.BeginTurn(); yield return original; } } [HarmonyPatch(typeof(CombatManager), "RunEndMonsterTurn")] internal static class TurnEndHook { private static void Postfix(ref IEnumerator __result) { __result = Run(__result); } private static IEnumerator Run(IEnumerator original) { yield return original; AcademicRuntime.EndTurn(); } } [HarmonyPatch] internal static class SpellResolutionHook { private static MethodBase TargetMethod() { return typeof(CombatManager).GetMethods().Single((MethodInfo m) => m.Name == "ApplyEffects" && m.GetParameters().FirstOrDefault()?.ParameterType == typeof(List<CardEffectState>)); } private static void Postfix(CardState playedCard, int selectedRoom, bool fromPlayedCard, CharacterState selfTarget, SpawnPoint dropLocation, ref IEnumerator __result) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (playedCard != null && fromPlayedCard && !playedCard.IsUnitAbility() && (int)playedCard.GetCardType() == 0) { __result = Run(__result, playedCard, selectedRoom, ((dropLocation != null) ? dropLocation.GetCharacterState() : null) ?? selfTarget); } } private static IEnumerator Run(IEnumerator original, CardState card, int floor, CharacterState target) { if (!AcademicRuntime.Active) { yield return original; yield break; } AcademicRuntime.SpellResolution frame = new AcademicRuntime.SpellResolution { Card = card, Floor = floor, FirstDamage = (card.GetIsDamageCard() && AcademicRuntime.FirstDamageSpell == null), WasFrozen = card.HasTrait(typeof(CardTraitFreeze)) }; if ((Object)(object)target != (Object)null && AcademicRuntime.Is(target, "WW_U01") && card.GetEffectStates().Any((CardEffectState e) => ((Enum)e.GetTargetTeamType()).HasFlag((Enum)(object)(Type)1)) && AcademicRuntime.Units(floor, (Type)1).Count > 0) { int statusEffectStacks = target.GetStatusEffectStacks("dazed"); frame.Redirected = true; if (statusEffectStacks > 0) { yield return AcademicRuntime.Core.GetCombatManager().ApplyDamageToTarget(AcademicMath.RedirectionDamage(statusEffectStacks), target, default(ApplyDamageToTargetParameters)); } if (!target.IsDestroyed && !target.IsDead) { target.AddStatusEffect("dazed", 1, (CharacterState)null, true, false); } AcademicRuntime.Core.GetPlayerManager().AddEnergy(card.GetLastPlayedCost(), false); target = AcademicRuntime.Units(floor, (Type)1).FirstOrDefault(); } try { yield return SpellRules.Before(frame, target); if (!frame.Indirect && (int)card.GetRarity() == 0) { AcademicRuntime.LastPlayedCommonSpell = card; } if (card.GetIsDamageCard()) { AcademicRuntime.DamageSpellPlayed = true; if (AcademicRuntime.FirstDamageSpell == null) { AcademicRuntime.FirstDamageSpell = card; } } AcademicRuntime.Frames.Push(frame); try { yield return original; } finally { AcademicRuntime.Frames.Pop(); } yield return AcademicRuntime.AfterSpell(frame); } finally { foreach (Action item in frame.Cleanup) { item(); } } } } [HarmonyPatch(typeof(CharacterState), "ApplyHeal")] internal static class HealHook { private static void Postfix(CharacterState __instance, int amount, CardState responsibleCard, bool fromMaxHPChange, ref IEnumerator __result) { __result = Run(__result, __instance, amount, responsibleCard, fromMaxHPChange); } private static IEnumerator Run(IEnumerator original, CharacterState unit, int amount, CardState source, bool fromMaxHPChange) { int before = unit.GetHP(); int healToTarget = unit.GetHealToTarget(amount, source, fromMaxHPChange, false); int excess = ((!fromMaxHPChange && amount < 9999) ? AcademicMath.ExcessHealing(healToTarget, before, unit.GetMaxHP()) : 0); yield return original; if (!unit.IsDestroyed && unit.IsAlive) { AcademicRuntime.RecordHeal(unit, Math.Max(0, unit.GetHP() - before), excess, source); yield return OverhealEvent.Dispatch(unit, excess, source); } } } public sealed class CardTraitAcademicConsumedDamage : CardTraitState { public override PropDescriptions CreateEditorInspectorDescriptions() { return PropDescriptions.DisplayNone; } public override int OnApplyingDamage(ApplyingDamageParameters damageParams, ICoreGameManagers coreGameManagers) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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) StatValueData statValueData = ((CardTraitState)this).StatValueData; statValueData.forPreviewText = false; int statValue = coreGameManagers.GetCardStatistics().GetStatValue(statValueData); return AcademicMath.ConsumedDamage(damageParams.damage, ((CardTraitState)this).GetParamInt(), statValue); } } public sealed class StatusEffectAcademicDissertation : StatusEffectState { } internal static class DissertationMarker { internal static string StatusId; internal static void Refresh(CharacterState unit) { if (!unit.IsDestroyed) { List<(CardState, int)> value; int num = ((SpellRules.BoundAttacks.TryGetValue(unit, out value) && value.Count > 0) ? value.Max<(CardState, int)>(((CardState card, int attacks) binding) => binding.attacks) : 0); int statusEffectStacks = unit.GetStatusEffectStacks(StatusId); if (num > statusEffectStacks) { unit.AddStatusEffect(StatusId, num - statusEffectStacks, (CharacterState)null, false, false); } else if (statusEffectStacks > num) { unit.RemoveStatusEffect(StatusId, statusEffectStacks - num, false); } } } internal static string Details(CharacterState unit) { if (!SpellRules.BoundAttacks.TryGetValue(unit, out List<(CardState, int)> value)) { return ""; } return string.Join("<br>", value.Select<(CardState, int), string>(((CardState card, int attacks) binding) => binding.card.GetTitle() + " — " + string.Format(LocalizationExtensions.Localize("david.wwinc.ReservedAttacks", (ILocalizationParameterContext)null), binding.attacks) + " — " + DissertationTargeting.SideLabel(binding.card))); } } [HarmonyPatch(typeof(TooltipUI), "GetStatusEffectCharacterContent")] internal static class DissertationMarkerTooltipHook { private static void Postfix(StatusEffectState statusEffectState, CharacterState characterState, ref TooltipContent __result) { if (!(statusEffectState.GetStatusId() != DissertationMarker.StatusId)) { string text = DissertationMarker.Details(characterState); if (!string.IsNullOrWhiteSpace(text)) { ref string body = ref __result.body; body = body + "<br><br>" + text; } } } } internal enum DissertationIntent { Unknown, Beneficial, Harmful } internal enum DissertationSide { Choose, Allies, Enemies } internal static class DissertationPolicy { internal static DissertationSide Resolve(IEnumerable<DissertationIntent> flexibleEffects) { bool flag = false; bool flag2 = false; bool flag3 = false; foreach (DissertationIntent flexibleEffect in flexibleEffects) { flag = flag || flexibleEffect == DissertationIntent.Beneficial; flag2 = flag2 || flexibleEffect == DissertationIntent.Harmful; flag3 = flag3 || flexibleEffect == DissertationIntent.Unknown; } if (flag3 || (flag && flag2)) { return DissertationSide.Choose; } if (!flag) { return DissertationSide.Enemies; } return DissertationSide.Allies; } } internal static class DissertationTargeting { internal sealed class Cast { internal CardState Card; internal CharacterState Owner; internal CharacterState Enemy; internal Type Side; } internal static CardData AllyChoice = null; internal static CardData EnemyChoice = null; internal static readonly Stack<Cast> Casts = new Stack<Cast>(); internal static bool CanBind(CardState card) { return card.GetEffectStates().Any((CardEffectState e) => (e.GetTargetTeamType() & 3) != 0 || (int)e.GetTargetMode() == 5 || e.GetCardEffect() is CardEffectRewardGold); } internal static DissertationSide PreferredSide(CardState card) { return DissertationPolicy.Resolve((from e in card.GetEffectStates() where (int)e.GetTargetMode() == 12 && ((Enum)e.GetTargetTeamType()).HasFlag((Enum)(object)(Type)2) && ((Enum)e.GetTargetTeamType()).HasFlag((Enum)(object)(Type)1) select e).Select(Intent)); } internal static DissertationIntent Intent(CardEffectState effect) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Invalid comparison between Unknown and I4 ICardEffect cardEffect = effect.GetCardEffect(); if (cardEffect is CardEffectHealAndDamageRelative) { return DissertationIntent.Unknown; } if (cardEffect is CardEffectDamage) { return DissertationIntent.Harmful; } if (SpellRules.HealingEffect(effect) || cardEffect is CardEffectRewardGold) { return DissertationIntent.Beneficial; } if (cardEffect is CardEffectAddStatusEffect) { StatusEffectStackData[] paramStatusEffectStackData = effect.GetParamStatusEffectStackData(); if (paramStatusEffectStackData.Length == 0) { return DissertationIntent.Unknown; } DissertationIntent dissertationIntent = DissertationIntent.Unknown; StatusEffectStackData[] array = paramStatusEffectStackData; foreach (StatusEffectStackData val in array) { StatusEffectData statusEffectDataById = StatusEffectManager.Instance.GetStatusEffectDataById(val.statusId, true); if (statusEffectDataById == null || val.count <= 0) { return DissertationIntent.Unknown; } DissertationIntent dissertationIntent2 = (((int)statusEffectDataById.GetDisplayCategory() == 0) ? DissertationIntent.Beneficial : (((int)statusEffectDataById.GetDisplayCategory() == 1) ? DissertationIntent.Harmful : DissertationIntent.Unknown)); if (dissertationIntent2 == DissertationIntent.Unknown || (dissertationIntent != DissertationIntent.Unknown && dissertationIntent2 != dissertationIntent)) { return DissertationIntent.Unknown; } dissertationIntent = dissertationIntent2; } return dissertationIntent; } if (cardEffect is CardEffectBuffDamage || cardEffect is CardEffectBuffMaxHealth) { if (effect.GetParamInt() <= 0) { if (effect.GetParamInt() >= 0) { return DissertationIntent.Unknown; } return DissertationIntent.Harmful; } return DissertationIntent.Beneficial; } if (cardEffect is CardEffectDebuffDamage || cardEffect is CardEffectDebuffMaxHealth) { return DissertationIntent.Harmful; } return DissertationIntent.Unknown; } internal static IEnumerator Bind(CardState selected, CharacterState owner, ICoreGameManagers core, ISystemManagers systems) { DissertationSide num = PreferredSide(selected); Type value = (Type)((num != DissertationSide.Allies) ? 1 : 2); if (num == DissertationSide.Choose) { CardState allies = new CardState(AllyChoice, core.GetSaveManager(), true, false); CardState enemies = new CardState(EnemyChoice, core.GetSaveManager(), true, false); CardState choice = null; yield return SpellRules.SelectPile(systems, (TargetMode)5, (CardState c) => c == allies || c == enemies, delegate(CardState c) { choice = c; }, cancel: false, new List<CardState> { allies, enemies }, "david.wwinc.DissertationChooseSide"); if (choice == null) { yield break; } value = (Type)((choice != allies) ? 1 : 2); } if (!owner.IsDestroyed && !owner.IsDead && core.GetCardManager().GetHand(false).Contains(selected)) { core.GetCardManager().MoveToStandByPile(selected, false, false, (RemoveFromStandByCondition)null, (DiscardCardParams)null, (DiscardEffect)0, false); SpellRules.ReservedCards.Add(selected); SpellRules.BoundSides[selected] = value; if (!SpellRules.BoundAttacks.TryGetValue(owner, out List<(CardState, int)> value2)) { value2 = (SpellRules.BoundAttacks[owner] = new List<(CardState, int)>()); } value2.Add((selected, 3)); DissertationMarker.Refresh(owner); } } internal static string SideLabel(CardState card) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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) Type value; Type val = ((card.GetEffectStates().Any((CardEffectState e) => (int)e.GetTargetMode() == 12 && ((Enum)e.GetTargetTeamType()).HasFlag((Enum)(object)(Type)2) && ((Enum)e.GetTargetTeamType()).HasFlag((Enum)(object)(Type)1)) && SpellRules.BoundSides.TryGetValue(card, out value)) ? value : card.GetTargetedTeamType((Type)0)); if (((Enum)val).HasFlag((Enum)(object)(Type)2) && ((Enum)val).HasFlag((Enum)(object)(Type)1)) { return LocalizationExtensions.Localize("david.wwinc.DissertationAllies", (ILocalizationParameterContext)null) + " / " + LocalizationExtensions.Localize("david.wwinc.DissertationEnemies", (ILocalizationParameterContext)null); } return LocalizationExtensions.Localize(((Enum)val).HasFlag((Enum)(object)(Type)1) ? "david.wwinc.DissertationEnemies" : "david.wwinc.DissertationAllies", (ILocalizationParameterContext)null); } internal static IEnumerator Repeat(CardState card, int floor, CharacterState owner, CharacterState enemy) { if (!owner.IsDestroyed && !owner.IsDead) { Type value; Cast cast = new Cast { Card = card, Owner = owner, Enemy = enemy, Side = (Type)((!SpellRules.BoundSides.TryGetValue(card, out value)) ? 1 : ((int)value)) }; CharacterState val = (((int)cast.Side == 2) ? owner : enemy); AcademicRuntime.SpellResolution frame = new AcademicRuntime.SpellResolution { Card = card, Floor = floor, Target = val, Indirect = true }; int previous = SpellRules.EffectFloor; SpellRules.EffectFloor = floor; Casts.Push(cast); AcademicRuntime.Frames.Push(frame); try { yield return AcademicRuntime.Core.GetCombatManager().ApplyEffects(card.GetEffectStates(), floor, card, false, (RelicState)null, owner, (SpawnPoint)null, true, (ApplyPreEffectsVfxAction)null, (ApplyPreEffectsAction)null, (ApplyEffectsAction)null, false, (CharacterState)null, (CharacterState)null, 1, val, false, (CardTriggerType)2, (CharacterTriggerState)null, (CharacterState)null, (RoomState)null, false, false, (CharacterState)null); } finally { AcademicRuntime.Frames.Pop(); Casts.Pop(); SpellRules.EffectFloor = previous; } yield return AcademicRuntime.AfterSpell(frame); } } } [HarmonyPatch(typeof(TargetHelper), "CheckTargetsOverride")] internal static class DissertationTargetOverride { private static bool Prefix(CardEffectState effectState, List<CharacterState> targets, ref CharacterState overrideTargetCharacter) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Invalid comparison between Unknown and I4 if (DissertationTargeting.Casts.Count == 0 || (int)effectState.GetTargetMode() != 12) { return true; } DissertationTargeting.Cast cast = DissertationTargeting.Casts.Peek(); if (effectState.GetParentCardState() != cast.Card) { return true; } Type targetTeamType = effectState.GetTargetTeamType(); bool flag = ((Enum)targetTeamType).HasFlag((Enum)(object)(Type)2); bool flag2 = ((Enum)targetTeamType).HasFlag((Enum)(object)(Type)1); overrideTargetCharacter = ((flag && (!flag2 || (int)cast.Side == 2)) ? cast.Owner : cast.Enemy); if (overrideTargetCharacter.IsDestroyed || overrideTargetCharacter.IsDead) { targets.Clear(); return false; } return true; } } internal static class EducationPreview { internal sealed class Scope { private readonly CardState card; private readonly CardUpgradeState upgrade; private bool finished; internal Scope(CardState card, int power) { this.card = card; upgrade = AcademicRuntime.PowerUpgrade(power, card.GetMagicPowerMultiplierFromTraits()); card.GetTemporaryCardStateModifiers().AddUpgrade(upgrade, (CardStateModifiers)null); TextDepth++; } internal void Finish() { if (finished) { return; } finished = true; try { card.GetTemporaryCardStateModifiers().RemoveUpgrade(upgrade); } finally { TextDepth--; } } } internal static int TextDepth; internal static int Power(CardState? card) { ICoreGameManagers core = AcademicRuntime.Core; if (core == null || AcademicRuntime.Simulating || TextDepth > 0 || card == null || !RoomPowerEligibility.Affected(card) || !core.GetCombatManager().IsPlayerActionPhase() || !core.GetCardManager().GetHand(false).Contains(card) || AcademicRuntime.Frames.Any((AcademicRuntime.SpellResolution frame) => frame.Card == card)) { return 0; } int selectedRoom = core.GetRoomManager().GetSelectedRoom(); if (selectedRoom >= 0 && !SpellRules.OnceTurn.Contains("FirstSpell:" + selectedRoom)) { return SpellRules.EducationPowerOnFloor(selectedRoom); } return 0; } } [HarmonyPatch(typeof(CardState), "GetCardText", new Type[] { typeof(CardStatistics), typeof(SaveManager), typeof(bool) })] internal static class EducationTextHook { private static void Prefix(CardState __instance, ref bool includeCurrentTraitEffectText, out EducationPreview.Scope? __state) { __state = null; int num = EducationPreview.Power(__instance); if (num > 0) { __state = new EducationPreview.Scope(__instance, num); includeCurrentTraitEffectText = true; } } private static void Postfix(EducationPreview.Scope? __state) { __state?.Finish(); } private static void Finalizer(EducationPreview.Scope? __state) { __state?.Finish(); } } [HarmonyPatch(typeof(CardUI), "LateUpdate")] internal static class EducationRefreshHook { internal sealed class View { internal CardState? Card; internal int Power = -1; internal int Multiplier; internal string Language = ""; } private static readonly ConditionalWeakTable<CardUI, View> views = new ConditionalWeakTable<CardUI, View>(); private static void Postfix(CardUI __instance, CardStatistics ___currentCardStats) { CardState cardState = __instance.GetCardState(); if (cardState != null && !((Object)(object)___currentCardStats == (Object)null) && RoomPowerEligibility.Affected(cardState)) { int num = EducationPreview.Power(cardState); int magicPowerMultiplierFromTraits = cardState.GetMagicPowerMultiplierFromTraits(); string text = LocalizationUtil.CurrentLanguage.ToString(); View value = views.GetValue(__instance, (CardUI _) => new View()); if (value.Card != cardState || value.Power != num || value.Multiplier != magicPowerMultiplierFromTraits || !(value.Language == text)) { value.Card = cardState; value.Power = num; value.Multiplier = magicPowerMultiplierFromTraits; value.Language = text; __instance.UpdateTextContent(cardState, ___currentCardStats, false); } } } } internal static class ExcessCredit { internal static CardData Template = null; internal static readonly Dictionary<CardState, CardState> Origins = new Dictionary<CardState, CardState>(); internal static bool IsCredit(CardState card) { return AcademicRuntime.Id(card).EndsWith("WW_Token_ExtraCredit", StringComparison.Ordinal); } internal static CharacterState? Owner(CardState? spell) { if (spell == null || !Origins.TryGetValue(spell, out CardState card)) { return null; } return AcademicRuntime.AllAllies().FirstOrDefault((Func<CharacterState, bool>)((CharacterState u) => u.GetSpawnerCard() == card)); } internal static void Generate(CharacterState attacker, int excess, int percent, CardUpgradeData? grantedUpgrade) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown if (!AcademicRuntime.Active || AcademicRuntime.Simulating || attacker.IsDestroyed || !attacker.IsAlive) { return; } int num = AcademicMath.ScaleOverdamage(excess, percent); CardState spawnerCard = attacker.GetSpawnerCard(); if (num <= 0 || spawnerCard == null) { return; } CardManager cardManager = AcademicRuntime.Core.GetCardManager(); CardState val = ((IEnumerable<CardState>)cardManager.GetHand(false)).FirstOrDefault((Func<CardState, bool>)IsCredit); if (val == null) { val = cardManager.AddNewCard(Template, (CardPile)((!cardManager.GetBelowHandSize()) ? 1 : 3), false, true, (AddCardUpgradingInfo)null, true); } if (val == null) { return; } if (!Origins.ContainsKey(val)) { Origins[val] = spawnerCard; } CardStateModifiers cardStateModifiers = val.GetCardStateModifiers(); if ((Object)(object)grantedUpgrade != (Object)null && !cardStateModifiers.HasUpgrade(((GameData)grantedUpgrade).GetID())) { CardUpgradeState val2 = new CardUpgradeState(); val2.Setup(grantedUpgrade, false, false); val2.SetAvoidClobberingExistingTraits(true); if (CardUpgradeHelper.TryApplyUpgradeToCard(val, spawnerCard, val2, false, AcademicRuntime.Core)) { val.ReapplyMagicPowerScalingFromTraitsToAllExistingUpgrades(AcademicRuntime.Core); } } long current = ((IEnumerable<int>)cardStateModifiers.GetAdditionalDamage()).Sum((Func<int, long>)((int value) => value)); cardStateModifiers.IncrementAdditionalDamage(AcademicMath.CreditDamageIncrement(current, num)); val.UpdateDamageText(); val.UpdateCardBodyText((SaveManager)null); cardManager.RefreshCardInHand(val, true, false, false); } internal static void RewardHandOwner(CardState? spell, int kills, ICoreGameManagers core) { if (kills > 0 && !core.GetSaveManager().PreviewMode && spell != null && !((Object)(object)Owner(spell) != (Object)null) && Origins.TryGetValue(spell, out CardState value) && core.GetCardManager().GetHand(false).Contains(value)) { CharacterData activeSavePyreCharacterData = core.GetSaveManager().GetActiveSavePyreCharacterData(); if (!(((activeSavePyreCharacterData != null) ? ((Object)activeSavePyreCharacterData).name : null) != "PyreHeartSavagery")) { value.GetCardStateModifiers().IncrementAdditionalDamage(kills); value.UpdateDamageText(); value.UpdateCardBodyText((SaveManager)null); core.GetCardManager().RefreshCardInHand(value, true, false, false); } } } } public sealed class CardEffectAcademicAuthoredDamage : CardEffectDamage { public override IEnumerator ApplyEffect(CardEffectState state, CardEffectParams parameters, ICoreGameManagers core, ISystemManagers systems) { CharacterState previous = parameters.selfTarget; CharacterState selfTarget = ExcessCredit.Owner(parameters.playedCard); CharacterState[] victims = parameters.targets.Where((CharacterState u) => !u.IsDestroyed && u.IsAlive && (int)u.GetTeamType() == 1).Distinct().ToArray(); parameters.selfTarget = selfTarget; try { yield return <>n__0(state, parameters, core, systems); } finally { parameters.selfTarget = previous; } if (!core.GetSaveManager().PreviewMode && !AcademicRuntime.Simulating) { ExcessCredit.RewardHandOwner(parameters.playedCard, victims.Count((CharacterState u) => (u.IsDestroyed || u.IsDead) && !MineMineMine.Claimed.Contains(u)), core); } } [CompilerGenerated] [DebuggerHidden] private IEnumerator <>n__0(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers, ISystemManagers sysManagers) { return ((CardEffectDamage)this).ApplyEffect(cardEffectState, cardEffectParams, coreGameManagers, sysManagers); } } [HarmonyPatch(typeof(CardManager), "AddNewCardCopy")] internal static class ExcessCreditCopyHook { private static void Postfix(CardState sourceCardState, CardState __result) { if (!AcademicRuntime.Simulating && __result != null && ExcessCredit.Origins.TryGetValue(sourceCardState, out CardState value)) { ExcessCredit.Origins[__result] = value; } } } internal sealed class ExcessCreditSave : ISaveData { [Serializable] public sealed class Entry { public int Spell; public int Owner; public string SpellData = ""; public string OwnerData = ""; } [Serializable] public sealed class Snapshot { public List<Entry> Entries = new List<Entry>(); } public string Key => "extra-credit-origins"; public bool ShouldSerialize() { if ((Object)(object)AllGameManagers.Instance != (Object)null) { return ExcessCredit.Origins.Count > 0; } return false; } public void Reset() { ExcessCredit.Origins.Clear(); } public string Serialize() { List<CardState> deckState = (AllGameManagers.Instance ?? throw new InvalidOperationException("Game managers unavailable for Extra Credit persistence.")).GetCoreManagers().GetSaveManager().GetDeckState(); Snapshot snapshot = new Snapshot(); foreach (KeyValuePair<CardState, CardState> origin in ExcessCredit.Origins) { int num = deckState.IndexOf(origin.Key); int num2 = deckState.IndexOf(origin.Value); if (num >= 0 && num2 >= 0) { snapshot.Entries.Add(new Entry { Spell = num, Owner = num2, SpellData = origin.Key.GetCardDataID(), OwnerData = origin.Value.GetCardDataID() }); } } return JsonUtility.ToJson((object)snapshot); } public void Deserialize(string payload) { //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Invalid comparison between Unknown and I4 Reset(); Snapshot snapshot = JsonUtility.FromJson<Snapshot>(payload); if (snapshot?.Entries == null) { return; } List<CardState> deckState = (AllGameManagers.Instance ?? throw new InvalidOperationException("Game managers unavailable for Extra Credit persistence.")).GetCoreManagers().GetSaveManager().GetDeckState(); foreach (Entry entry in snapshot.Entries) { if (entry.Spell >= 0 && entry.Spell < deckState.Count && entry.Owner >= 0 && entry.Owner < deckState.Count) { CardState val = deckState[entry.Spell]; CardState val2 = deckState[entry.Owner]; if (ExcessCredit.IsCredit(val) && !(val.GetCardDataID() != entry.SpellData) && !(val2.GetCardDataID() != entry.OwnerData) && (int)val2.GetCardType() == 1) { ExcessCredit.Origins[val] = val2; } } } } } public sealed class StatusEffectAcademicInsurance : StatusEffectState { } public sealed class CardEffectAcademicWizardDraw : AcademicEffectBase, ICardTargetingCardEffect, ICardEffectDrawsCards, ICardEffect { private readonly CardEffectDrawType nativeDraw = new CardEffectDrawType(); internal static CardUpgradeData NextUseUpgrade; public override bool CanPlayAfterBossDead => false; public override bool CanApplyInPreviewMode => true; public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { CardManager cardManager = m.GetCardManager(); CardUpgradeMaskData filter = s.GetParamCardFilter(); if (!cardManager.GetDrawingDeckCardsDisabledThisTurn() && cardManager.GetBelowHandSize() && (Object)(object)filter != (Object)null) { return cardManager.GetDrawPile(false).Concat(cardManager.GetDiscardPile(false)).Any((CardState c) => c != p.playedCard && filter.FilterCard<CardState>(c, m.GetRelicManager())); } return false; } public int GetNumCardTargets(CardState card, CardEffectState effect, CardStatistics statistics) { return nativeDraw.GetNumCardTargets(card, effect, statistics); } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { if (!m.GetSaveManager().PreviewMode && ((CardEffectBase)this).TestEffect(s, p, m)) { AcademicRuntime.Core = m; CardUpgradeState val = new CardUpgradeState(); val.Setup(NextUseUpgrade, false, false); val.SetAvoidClobberingExistingTraits(true); m.GetCardManager().AddTempCardUpgradeToNextDrawnCard(val); yield return ((CardEffectBase)nativeDraw).ApplyEffect(s, p, m, systems); } } internal static int Rank(CharacterState? unit, string prefix) { if (!((Object)(object)unit == (Object)null)) { return AcademicMath.ChampionRank(from u in ChampionPathText.Selected(unit.GetSpawnerCard(), unit) select u.GetAssetName(), prefix); } return 0; } } public sealed class CardEffectAcademicPurgePermit : AcademicEffectBase { private static readonly RingPermitLedger Permit = new RingPermitLedger(); public override bool CanApplyInPreviewMode => true; internal static void BeginBattle(ICoreGameManagers core) { Permit.BeginBattle(Ring(core), SaveManager.IsInUndoModeStatic); } private static string Ring(ICoreGameManagers core) { return core.GetSaveManager().GetRunId() + ":" + core.GetSaveManager().GetRunState().GetLoopIndex() + ":" + core.GetSaveManager().GetRunState().GetCurrentDistance(); } private static CardState? Equipment(CardEffectState effect, CardEffectParams parameters) { CardState? obj = effect.GetParentEquipment(); if (obj == null) { CharacterState obj2 = parameters.characterThatActivatedAbility ?? parameters.selfTarget; if (obj2 == null) { return null; } obj = ((IEnumerable<CardState>)obj2.GetEquipment()).LastOrDefault((Func<CardState, bool>)((CardState card) => AcademicRuntime.Id(card).EndsWith("WW_E01", StringComparison.Ordinal))); } return obj; } private static bool Eligible(CardState card, CardEffectState effect, ICoreGameManagers managers, CardState equipment) { CardUpgradeMaskData paramCardFilter = effect.GetParamCardFilter(); if (Permit.Available(Ring(managers), equipment) && (Object)(object)paramCardFilter != (Object)null) { return paramCardFilter.FilterCard<CardState>(card, managers.GetRelicManager()); } return false; } public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { CardState equipment = Equipment(s, p); if (equipment != null) { return m.GetCardManager().GetHand(false).Any((CardState c) => c != p.playedCard && Eligible(c, s, m, equipment)); } return false; } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { if (m.GetSaveManager().PreviewMode) { yield break; } AcademicRuntime.Core = m; CardState equipment = Equipment(s, p); if (equipment != null && ((CardEffectBase)this).TestEffect(s, p, m)) { yield return AcademicRuntime.ChooseHand(p.playedCard, (CardState c) => Eligible(c, s, m, equipment), delegate(CardState card) { AcademicRuntime.Core = m; string key = Ring(m); AcademicRuntime.Trait(card, "CardTraitSelfPurge"); Permit.MarkUsed(key, equipment); }); } } } [HarmonyPatch(typeof(CharacterState), "GetAttackDamage")] internal static class ZeroAttackHook { private static void Postfix(CharacterState __instance, ref int __result) { if (AcademicRuntime.Active && AcademicRuntime.ZeroAttack.Contains(__instance)) { __result = 0; } } } internal static class RedirectTargets { internal static List<CharacterState> InRoom(RoomState? room, Type team) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) List<CharacterState> list = new List<CharacterState>(); if ((Object)(object)room != (Object)null) { room.AddCharactersToList(list, team, false, true); } return list.Where((CharacterState u) => !u.IsDead && !u.IsDestroyed).ToList(); } } [HarmonyPatch] internal static class EligibleRedirectHook { private static MethodBase TargetMethod() { return typeof(TargetHelper).GetMethods().Single((MethodInfo m) => m.Name == "CollectTargets" && m.GetParameters()[0].ParameterType == typeof(CardEffectState)); } private static void Postfix(CardEffectState effectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Invalid comparison between Unknown and I4 CardState playedCard = cardEffectParams.playedCard; if (playedCard == null || playedCard.IsUnitAbility() || (int)playedCard.GetCardType() != 0 || (coreGameManagers.GetSaveManager().PreviewMode && !PreviewScope.Active)) { return; } AcademicRuntime.Core = coreGameManagers; if (SpellRules.IsAreaEffect(playedCard, effectState)) { cardEffectParams.targets.Clear(); cardEffectParams.targets.AddRange(RedirectTargets.InRoom(coreGameManagers.GetRoomManager().GetRoom(cardEffectParams.selectedRoom), (Type)1)); } else if (((Enum)effectState.GetTargetTeamType()).HasFlag((Enum)(object)(Type)1) && (int)effectState.GetTargetMode() == 12 && RedirectTargets.InRoom(coreGameManagers.GetRoomManager().GetRoom(cardEffectParams.selectedRoom), (Type)1).Count > 0) { cardEffectParams.targets.AddRange(from u in RedirectTargets.InRoom(coreGameManagers.GetRoomManager().GetRoom(cardEffectParams.selectedRoom), (Type)2) where AcademicRuntime.Is(u, "WW_U01") && !cardEffectParams.targets.Contains(u) select u); } } } [HarmonyPatch(typeof(TargetHelper), "CheckTargetsOverride")] internal static class RedirectTargetHook { private static bool Prefix(CardEffectState effectState, List<CharacterState> targets, SpawnPoint dropLocation, ref CharacterState overrideTargetCharacter) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) CardState parentCardState = effectState.GetParentCardState(); if (parentCardState == null || parentCardState.IsUnitAbility()) { return true; } if (SpellRules.IsAreaEffect(parentCardState, effectState)) { return false; } if (SpellRules.EffectFloor >= 0) { return true; } if (AcademicRuntime.Frames.Count > 0 && AcademicRuntime.Frames.Peek().Card == parentCardState && AcademicRuntime.Frames.Peek().Redirected && ((Enum)effectState.GetTargetTeamType()).HasFlag((Enum)(object)(Type)1)) { overrideTargetCharacter = AcademicRuntime.Frames.Peek().Target; return true; } CharacterState val = ((dropLocation != null) ? dropLocation.GetCharacterState() : null); if ((Object)(object)val != (Object)null && AcademicRuntime.Is(val, "WW_U01") && ((Enum)effectState.GetTargetTeamType()).HasFlag((Enum)(object)(Type)1)) { CharacterState val2 = RedirectTargets.InRoom(val.GetCurrentRoom(false), (Type)1).FirstOrDefault(); if ((Object)(object)val2 != (Object)null) { overrideTargetCharacter = val2; } } return true; } } public sealed class CardEffectAcademicDiscardForEmber : AcademicEffectBase { public override bool CanApplyInPreviewMode => true; internal static bool Eligible(CardState card) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 CardType cardType = card.GetCardType(); bool flag = (((int)cardType == 0 || cardType - 5 <= 1) ? true : false); if (flag && !card.HasTrait(typeof(CardTraitPersistent))) { return !card.HasTrait(typeof(CardTraitInfusion)); } return false; } public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { return m.GetCardManager().GetHand(false).Any((CardState c) => c != p.playedCard && Eligible(c)); } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { if (!m.GetSaveManager().PreviewMode) { AcademicRuntime.Core = m; yield return AcademicRuntime.ChooseHand(p.playedCard, Eligible, (CardState card) => ResolveWithdrawal(card, p, m)); } } private static IEnumerator ResolveWithdrawal(CardState card, CardEffectParams p, ICoreGameManagers m) { AcademicRuntime.Core = m; CardManager manager = m.GetCardManager(); if (manager.GetHand(false).Contains(card) && Eligible(card)) { int cost = (int)Math.Min(2147483647L, 2L * (long)Math.Max(0, SpellRules.Cost(card))); yield return manager.DiscardCard(new DiscardCardParams { discardCard = card, triggeredByCard = true, triggeredCard = p.playedCard, wasPlayed = false }, false); if (!manager.GetHand(false).Contains(card)) { m.GetPlayerManager().AddEnergy(cost, false); } } } } [HarmonyPatch(typeof(CombatManager), "GetTargetCharacters")] internal static class RedirectUiHook { private static void Postfix(List<CharacterState> outCharacters, CardState cardState, RoomState room) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (cardState == null || (Object)(object)room == (Object)null || cardState.IsAnyAbility() || (int)cardState.GetCardType() != 0 || !cardState.GetEffectStates().Any((CardEffectState e) => ((Enum)e.GetTargetTeamType()).HasFlag((Enum)(object)(Type)1)) || RedirectTargets.InRoom(room, (Type)1).Count == 0) { return; } foreach (CharacterState item in from u in RedirectTargets.InRoom(room, (Type)2) where AcademicRuntime.Is(u, "WW_U01") select u) { if (!outCharacters.Contains(item)) { outCharacters.Add(item); } } } } [HarmonyPatch(typeof(CardState), "GetCost")] internal static class FixedCostHook { private static bool Prefix(CardState __instance, ref int __result) { if (AcademicRuntime.Active && AcademicRuntime.FixedCosts.TryGetValue(__instance, out var value)) { __result = value; return false; } return true; } } [HarmonyPatch(typeof(CardState), "IsConsumeRemainingEnergyCostType")] internal static class FixedXCostHook { private static void Postfix(CardState __instance, ref bool __result) { if (AcademicRuntime.Active && AcademicRuntime.FixedCosts.ContainsKey(__instance)) { __result = false; } } } [HarmonyPatch(typeof(CombatManager), "RunUnitTurn")] internal static class AttackSequenceHook { private static void Prefix(CharacterState attackerState, ref Action<int> perAttackVfxCallback, out List<CardState> __state) { __state = new List<CardState>(); if (!AcademicRuntime.Active) { return; } List<CardState> seen = __state; Action<int> original = perAttackVfxCallback; perAttackVfxCallback = delegate(int index) { AcademicRuntime.BoundForAttack[attackerState] = new List<CardState>(); if (SpellRules.BoundAttacks.TryGetValue(attackerState, out List<(CardState, int)> value)) { (CardState, int)[] array = value.ToArray(); for (int i = 0; i < array.Length; i++) { (CardState, int) item = array[i]; AcademicRuntime.BoundForAttack[attackerState].Add(item.Item1); seen.Add(item.Item1); value.Remove(item); if (item.Item2 > 1) { value.Add((item.Item1, item.Item2 - 1)); } } if (value.Count == 0) { SpellRules.BoundAttacks.Remove(attackerState); } } DissertationMarker.Refresh(attackerState); original?.Invoke(index); }; } private static void Postfix(CharacterState attackerState, List<CardState> __state, ref IEnumerator __result) { __result = Run(__result, attackerState, __state); } private static IEnumerator Run(IEnumerator original, CharacterState unit, List<CardState> seen) { try { yield return original; } finally { AcademicRuntime.BoundForAttack.Remove(unit); } foreach (CardState item in seen.Distinct()) { yield return SpellRules.ReleaseBoundSpell(item); } } } internal static class RedirectTeamScope { internal static readonly Stack<CardState> Cards = new Stack<CardState>(); } [HarmonyPatch(typeof(CharacterTargetValidator), "IsValidTarget")] internal static class RedirectTeamValidationHook { private static void Prefix(CharacterTargetValidator __instance, RoomState selectedRoom, SpawnPointUI selectedSpawnPointUI, out bool __state) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) __state = false; CardState activeCard = ((TargetValidator)__instance).GetActiveCard(); object obj; if (selectedSpawnPointUI == null) { obj = null; } else { SpawnPoint parentSpawnPoint = selectedSpawnPointUI.GetParentSpawnPoint(); obj = ((parentSpawnPoint != null) ? parentSpawnPoint.GetCharacterState() : null); } CharacterState val = (CharacterState)obj; if (activeCard != null && !((Object)(object)selectedRoom == (Object)null) && !((Object)(object)val == (Object)null) && !val.IsDead && !val.IsDestroyed && !activeCard.IsAnyAbility() && (int)activeCard.GetCardType() == 0 && AcademicRuntime.Is(val, "WW_U01") && activeCard.GetEffectStates().Any((CardEffectState e) => ((Enum)e.GetTargetTeamType()).HasFlag((Enum)(object)(Type)1)) && RedirectTargets.InRoom(selectedRoom, (Type)1).Count != 0) { RedirectTeamScope.Cards.Push(activeCard); __state = true; } } private static void Finalizer(bool __state) { if (__state) { RedirectTeamScope.Cards.Pop(); } } } [HarmonyPatch(typeof(CardState), "GetTargetedTeamType")] internal static class RedirectCardTeamHook { private static void Postfix(CardState __instance, ref Type __result) { if (RedirectTeamScope.Cards.Count > 0 && RedirectTeamScope.Cards.Peek() == __instance) { __result = (Type)((uint)__result | 2u); } } } public sealed class CardEffectAcademicCopyLastCommon : AcademicEffectBase { public override bool TestEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m) { CardState lastPlayedCommonSpell = AcademicRuntime.LastPlayedCommonSpell; if (lastPlayedCommonSpell != null && lastPlayedCommonSpell.CanBeCopied()) { return m.GetCardManager().GetBelowHandSize(); } return false; } public override IEnumerator ApplyEffect(CardEffectState s, CardEffectParams p, ICoreGameManagers m, ISystemManagers systems) { if (!m.GetSaveManager().PreviewMode) { AcademicRuntime.Core = m; CardState lastPlayedCommonSpell = AcademicRuntime.LastPlayedCommonSpell; if (lastPlayedCommonSpell != null) { SpellRules.CopyEphemeral(lastPlayedCommonSpell); } } yield break; } } [HarmonyPatch(typeof(MonsterManager), "RemoveCharacter")] internal static class DeathHook { private static void Prefix(CharacterState removeCharacter, bool death, ref bool vanishUnit) { if (AcademicRuntime.Active && death && ((Object)removeCharacter.GetSourceCharacterData()).name.Contains("WW_Token_")) { vanishUnit = true; } } private static void Postfix(CharacterState removeCharacter, bool death, ref IEnumerator __result) { if (AcademicRuntime.Active && death) { __result = Run(__result, removeCharacter); } } private static IEnumerator Run(IEnumerator original, CharacterState unit) { int floor = unit.GetCurrentRoomIndex(); bool chaperone = SocialRules.Chaperone != null && unit.GetHasSubtype(SocialRules.Chaperone); List<CardState> value; CardState[] archived = (SpellRules.Archived.TryGetValue(unit, out value) ? value.ToArray() : Array.Empty<CardState>()); List<(CardState, int)> value2; CardState[] bound = (SpellRules.BoundAttacks.TryGetValue(unit, out value2) ? value2.Select<(CardState, int), CardState>(((CardState card, int attacks) b) => b.card).ToArray() : Array.Empty<CardState>()); if (AcademicRuntime.BoundForAttack.TryGetValue(unit, out List<CardState> value3)) { bound = bound.Concat(value3).Distinct().ToArray(); } yield return original; SpellRules.BoundAttacks.Remove(unit); CardState[] array = bound; foreach (CardState card in array) { yield return SpellRules.ReleaseBoundSpell(card); } if (!unit.IsDestroyed) { DissertationMarker.Refresh(unit); } if (!AcademicRuntime.Simulating && archived.Length != 0) { SpellRules.Archived.Remove(unit); array = archived; foreach (CardState card2 in array) { yield return SpellRules.Restore(card2, ephemeral: false, attuned: true, zero: true, attunedThisTurn: true); } } if (chaperone && SpellRules.HasRelic("WW_A08") && SpellRules.OnceTurn.Add("A08")) { foreach (CharacterState item in AcademicRuntime.Units(floor, (Type)2)) { if (item.GetStatusEffectStacks("cooldown") > 0) { item.RemoveStatusEffect("cooldown", 1, true); } } } SocialRules.RefreshAuras(); } } [HarmonyPatch(typeof(CharacterState), "GetUnitAbilityCooldown")] internal static class PlatonicCooldownHook { private static void Postfix(CharacterState __instance, ref int __result) { if (AcademicRuntime.Core == null || SocialRules.Wizard == null || __instance.IsDestroyed) { return; } RoomState currentRoom = __instance.GetCurrentRoom(false); if ((Object)(object)currentRoom == (Object)null || !currentRoom.GetRoomStateModifiersFromTrainRoomAttachments<RoomStateAcademicPlatonic>((Type)2).Any()) { return; } List<CharacterState> list = AcademicRuntime.Units(currentRoom.GetRoomIndex(), (Type)2); for (int i = 0; i + 1 < list.Count; i++) { if (SocialRules.Mixed(list[i], list[i + 1]) && ((Object)(object)list[i] == (Object)(object)__instance || (Object)(object)list[i + 1] == (Object)(object)__instance)) { __result = Math.Max(1, __result - 1); break; } } } } [HarmonyPatch(typeof(CharacterState), "SetSpawnPoint")] internal static class AuraPositionHook { private static void Postfix() { SocialRules.RefreshAuras(); } } [HarmonyPatch(typeof(CharacterState), "ApplyDamage")] internal static class UnitAttackHook { private static void Prefix(ref int damage, ApplyDamageParams damageParams) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0018: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (AcademicRuntime.Active && damageParams.damageSourceCard != null && (int)damageParams.damageType != 10 && SpellRules.DamageFactors.TryGetValue(damageParams.damageSourceCard, out var value)) { damage = (int)Math.Floor((float)damage * value); } } private static void Postfix(CharacterState __instance, int damage, ApplyDamageParams damageParams, ref IEnumerator __result) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) __result = Run(__result, __instance, damage, damageParams); } private static IEnumerator Run(IEnumerator original, CharacterState target, int damage, ApplyDamageParams parameters) { //IL_001c: 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) if (!AcademicRuntime.Active) { yield return original; yield break; } CharacterState attacker = parameters.attacker; bool direct = (int)parameters.damageType == 4; int hp = target.GetHP(); int floor = target.GetCurrentRoomIndex(); bool dead = target.IsDead; yield return original; AcademicRuntime.RecordDamage(target, Math.Max(0, hp - ((!target.IsDestroyed) ? target.GetHP() : 0)), !dead && (target.IsDead || target.IsDestroyed), parameters.damageSourceCard, attacker, floor); if ((Object)(object)attacker != (Object)null && direct) { List<CardState> list = new List<CardState>(); List<CardState> completed = new List<CardState>(); List<(CardState, int)> value2; if (AcademicRuntime.BoundForAttack.TryGetValue(attacker, out List<CardState> value)) { list.AddRange(value); } else if (SpellRules.BoundAttacks.TryGetValue(attacker,