Decompiled source of FreeCompany v0.3.5
plugins/mt2_freecompany.Plugin.dll
Decompiled 5 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.Reflection.Emit; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Microsoft.Extensions.Configuration; using Newtonsoft.Json.Linq; using ShinyShoe; using TrainworksReloaded.Core; using TrainworksReloaded.Core.Extensions; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyFileVersion("0.3.5.0")] [assembly: AssemblyInformationalVersion("0.3.5+50504b8924c8785c9312b79da0b05fb898c3f8a8")] [assembly: AssemblyVersion("0.3.5.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 mt2_freecompany.Plugin { [BepInPlugin("mt2_freecompany.Plugin", "mt2_freecompany.Plugin", "0.3.5")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger = new ManualLogSource("mt2_freecompany.Plugin"); internal static int ApplyPatches(Harmony harmony, IEnumerable<Type> types) { int num = 0; foreach (Type type in types) { try { harmony.CreateClassProcessor(type).Patch(); } catch (Exception arg) { num++; Logger.LogError((object)$"FreeCompany failed to patch {type.FullName}: {arg}"); } } return num; } public void Awake() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; Railhead.GetBuilder().Configure("mt2_freecompany.Plugin", (Action<IConfigurationBuilder>)delegate(IConfigurationBuilder c) { ConfigurationExtensions.AddMergedJsonFile(c, new List<string>(79) { "json/plugin.json", "json/champions/champion_roderic.json", "json/champions/champion_roderic_wall.json", "json/champions/champion_roderic_quartermaster.json", "json/champions/champion_roderic_plunder.json", "json/champions/champion_vesper.json", "json/champions/champion_vesper_grimoire.json", "json/champions/champion_vesper_chirurgeon.json", "json/champions/champion_vesper_beastmaster.json", "json/cards/card_magic_missile.json", "json/cards/card_field_dressing.json", "json/cards/card_shield_wall.json", "json/units/unit_battle_chaplain.json", "json/units/unit_berserker.json", "json/units/unit_bounty_hunter.json", "json/units/unit_camp_brawler.json", "json/units/unit_chapel_acolyte.json", "json/units/unit_cutpurse.json", "json/units/unit_fieldmedic.json", "json/units/unit_free_lance.json", "json/units/unit_hedge_conjurer.json", "json/units/unit_hedgemage.json", "json/units/unit_ironbound_champion.json", "json/units/unit_longbowman.json", "json/units/unit_master_of_coin.json", "json/units/unit_sellsword_scout.json", "json/units/unit_shieldbearer.json", "json/units/unit_the_new_guy.json", "json/units/unit_troll.json", "json/spells/spell_banishment.json", "json/spells/spell_bless.json", "json/spells/spell_cloudkill.json", "json/spells/spell_cure_wounds.json", "json/spells/spell_delayed_blast_fireball.json", "json/spells/spell_dimension_door.json", "json/spells/spell_fear.json", "json/spells/spell_finger_of_death.json", "json/spells/spell_fireball.json", "json/spells/spell_grease.json", "json/spells/spell_haste.json", "json/spells/spell_invisibility.json", "json/spells/spell_lightning_bolt.json", "json/spells/spell_mass_hold_person.json", "json/spells/spell_mercenarys_contract.json", "json/spells/spell_paid_in_full.json", "json/spells/spell_resurrection.json", "json/spells/spell_shield.json", "json/spells/spell_silence.json", "json/spells/spell_spoils_of_war.json", "json/spells/spell_web.json", "json/spells/spell_severance_pay.json", "json/spells/spell_kit_bash.json", "json/spells/spell_double_shift.json", "json/rooms/room_caltrops.json", "json/rooms/room_paymasters_tent.json", "json/rooms/room_rope_and_grapple.json", "json/rooms/room_the_pit.json", "json/rooms/room_quartermasters_store.json", "json/rooms/room_watchtower.json", "json/kits/kit_barbarian.json", "json/kits/kit_cleric.json", "json/kits/kit_ranger.json", "json/kits/kit_rogue.json", "json/kits/kit_warrior.json", "json/kits/kit_wizard.json", "json/equipment/equip_widows_pension.json", "json/relics/relic_butchers_bill.json", "json/relics/relic_expanded_billet.json", "json/relics/relic_field_forge.json", "json/relics/relic_hazard_pay.json", "json/relics/relic_letter_of_marque.json", "json/relics/relic_marching_orders.json", "json/relics/relic_quartermasters_seal.json", "json/relics/relic_sappers_charges.json", "json/relics/relic_scouts_map.json", "json/relics/relic_veterans_papers.json", "json/relics/relic_war_chest.json", "json/status/status_countdown.json", "json/status/status_dizzy.json" }); }); int num = ApplyPatches(new Harmony("mt2_freecompany.Plugin"), typeof(Plugin).Assembly.GetTypes()); if (num == 0) { Logger.LogInfo((object)"Plugin mt2_freecompany.Plugin is loaded!"); } else { Logger.LogError((object)($"FreeCompany initialized with {num} failed Harmony patch classes. " + "Some features are unavailable; inspect the errors above before playing.")); } } } [HarmonyPatch(typeof(CardState), "GenerateCardBodyText")] internal static class BeastmasterCardText { private static void Postfix(CardState __instance, ref string generatedText) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown if (__instance.GetAssetName() != "mt2_freecompany.Plugin-Card-SpawnVesper") { return; } CardStateModifiers cardStateModifiers = __instance.GetCardStateModifiers(); List<CardUpgradeState> list = ((cardStateModifiers != null) ? cardStateModifiers.GetCardUpgrades() : null); if (list == null) { return; } for (int num = 3; num >= 1; num--) { string text = "mt2_freecompany.Plugin-Upgrade-upg_Beastmaster" + num; foreach (CardUpgradeState item in list) { if (item == null || item.GetAssetName() != text) { continue; } CardUpgradeData sourceCardUpgradeData = item.GetSourceCardUpgradeData(); if (!((Object)(object)sourceCardUpgradeData == (Object)null)) { string text2 = LocalizationExtensions.Localize(item.GetUpgradeDescriptionKey(), (ILocalizationParameterContext)new CardEffectLocalizationContext((ILocalizationEffectPower)(object)sourceCardUpgradeData, (CharacterState)null, __instance, (IRoomStateModifier)null, (CharacterStatusEffectAdjustments)null)); if (!string.IsNullOrWhiteSpace(text2) && (generatedText == null || generatedText.IndexOf(text2, StringComparison.Ordinal) < 0)) { generatedText = (string.IsNullOrWhiteSpace(generatedText) ? text2 : (generatedText + "\n" + text2)); } return; } } } } } internal static class BeastmasterMarkers { internal const string StatusId = "mt2_freecompany.plugin_tamed"; internal static CardUpgradeState? HandMarker(CardState? card) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown AllGameManagers instance = AllGameManagers.Instance; if (card == null || (Object)(object)instance == (Object)null || !instance.AreMainSceneOnlyManagersInitialized()) { return null; } CardManager cardManager = instance.GetCardManager(); if ((Object)(object)cardManager == (Object)null || !cardManager.IsCardInHand(card) || !BeastmasterTraining.IsCreature(card)) { return null; } ICoreGameManagers coreManagers = instance.GetCoreManagers(); if (!BeastmasterTraining.HasBeastmasterInRun(coreManagers)) { return null; } AllGameData allGameData = coreManagers.GetAllGameData(); CardUpgradeData val = ((allGameData == null) ? null : allGameData.GetAllCardUpgradeData()?.FirstOrDefault((Func<CardUpgradeData, bool>)((CardUpgradeData u) => (Object)(object)u != (Object)null && ((Object)u).name == "mt2_freecompany.Plugin-Upgrade-TamableMarker"))); if ((Object)(object)val == (Object)null) { return null; } CardUpgradeState val2 = new CardUpgradeState(); val2.Setup(val, false, false); return val2; } internal static void MarkTrained(CharacterState unit) { AllGameManagers instance = AllGameManagers.Instance; if (!((Object)(object)instance == (Object)null) && instance.AreMainSceneOnlyManagersInitialized()) { ICoreGameManagers coreManagers = instance.GetCoreManagers(); CardState spawnerCard = unit.GetSpawnerCard(); if (coreManagers != null && !coreManagers.GetSaveManager().PreviewMode && spawnerCard != null && !unit.HasStatusEffect("mt2_freecompany.plugin_tamed") && spawnerCard.GetCardStateModifiers().GetCardUpgrades().Any((CardUpgradeState u) => u.GetCardUpgradeDataId() == "bde5128c-6744-4365-8915-fc62f9f5369e")) { unit.AddStatusEffect("mt2_freecompany.plugin_tamed", 1, CharacterState.defaultAddStatusEffectParams, (CharacterState)null, false, false, false, true, true); } } } } [HarmonyPatch(typeof(CardUpgradeDisplayContainer), "DisplayUpgrades")] internal static class BeastmasterHandIconPatch { private static void Prefix(CardUpgradeDisplayContainer __instance, ref List<CardUpgradeState> temporaryUpgrades, bool ____isRegionRunDisplay) { if (!____isRegionRunDisplay) { CardUI componentInParent = ((Component)__instance).GetComponentInParent<CardUI>(); CardUpgradeState val = BeastmasterMarkers.HandMarker((componentInParent != null) ? componentInParent.GetCardState() : null); if (val != null) { temporaryUpgrades = new List<CardUpgradeState>(temporaryUpgrades); temporaryUpgrades.Add(val); } } } } [HarmonyPatch(typeof(CardTooltipContainer), "AddTooltipsForCardState")] internal static class BeastmasterHandTooltipPatch { private static void Postfix(CardTooltipContainer __instance, CardState cardState, SaveManager saveManager) { CardUpgradeState val = BeastmasterMarkers.HandMarker(cardState); if (val != null) { ((TooltipContainer)__instance).AddTooltipsCardUpgrade(cardState, val, saveManager); } } } [HarmonyPatch(typeof(CharacterState), "OnSpawn")] internal static class BeastmasterTamedSpawnPatch { private static void Postfix(CharacterState __instance, ref IEnumerator __result) { __result = AfterSpawn(__instance, __result); } private static IEnumerator AfterSpawn(CharacterState unit, IEnumerator original) { while (original.MoveNext()) { yield return original.Current; } BeastmasterMarkers.MarkTrained(unit); AllGameManagers instance = AllGameManagers.Instance; if ((Object)(object)instance != (Object)null && instance.AreMainSceneOnlyManagersInitialized()) { yield return BeastmasterTraining.TrainDeployed(instance.GetCoreManagers()); } } } public sealed class StatusEffectFreeCompanyTamedState : StatusEffectState { public override bool TestTrigger(InputTriggerParams input, OutputTriggerParams output, ICoreGameManagers core) { return false; } } [HarmonyPatch(typeof(CharacterTooltipHelper), "GetAdditionalTooltipContents")] internal static class BeastmasterChampionTooltipPatch { private const string TooltipId = "mt2_freecompany.BeastmasterRules"; private static void Postfix(CharacterState characterState, SaveManager saveManager, ref IEnumerable<(TooltipContent content, bool allowDuplicates)> __result) { __result = AppendRules(__result, characterState, saveManager); } internal static IEnumerable<(TooltipContent content, bool allowDuplicates)> AppendRules(IEnumerable<(TooltipContent content, bool allowDuplicates)> original, CharacterState character, SaveManager save) { bool alreadyShown = false; foreach (var item in original) { if (item.content.tooltipId == "mt2_freecompany.BeastmasterRules") { alreadyShown = true; } yield return item; } if (alreadyShown || (Object)(object)character == (Object)null || (Object)(object)save == (Object)null) { yield break; } AllGameData allGameData = save.GetAllGameData(); if ((Object)(object)allGameData == (Object)null) { yield break; } CardState spawnerCard = character.GetSpawnerCard(); for (int num = 3; num >= 1; num--) { string name = "mt2_freecompany.Plugin-Upgrade-upg_Beastmaster" + num; CardUpgradeData val = ((IEnumerable<CardUpgradeData>)allGameData.GetAllCardUpgradeData()).FirstOrDefault((Func<CardUpgradeData, bool>)((CardUpgradeData u) => (Object)(object)u != (Object)null && ((Object)u).name == name)); if (!((Object)(object)val == (Object)null) && (character.HasUpgrade(val) || (spawnerCard != null && spawnerCard.HasUpgrade(val)))) { CardUpgradeState val2 = new CardUpgradeState(); val2.Setup(val, false, false); string text = LocalizationExtensions.Localize(val2.GetUpgradeDescriptionKey(), (ILocalizationParameterContext)new CardEffectLocalizationContext((ILocalizationEffectPower)(object)val, (CharacterState)null, spawnerCard, (IRoomStateModifier)null, (CharacterStatusEffectAdjustments)null)); yield return (content: new TooltipContent(val2.GetUpgradeTitle(), text, (TooltipDesignType)8, "mt2_freecompany.BeastmasterRules", false, false), allowDuplicates: false); break; } } } } internal static class BeastmasterTraining { [HarmonyPatch(typeof(CombatManager), "RunMonsterTurn")] private static class StartTurnPatch { [HarmonyPostfix] private static void Postfix(ref IEnumerator __result) { __result = BeforeTurn(__result); } } [HarmonyPatch(typeof(RelicManager), "ApplyCardAddedToHandRelicEffects")] private static class HandEntryPatch { [HarmonyPostfix] private static void Postfix(CardState cardState) { AllGameManagers instance = AllGameManagers.Instance; ICoreGameManagers val = ((instance != null) ? instance.GetCoreManagers() : null); if (val != null) { Freeze(cardState, val); } } } internal const string TrainingId = "bde5128c-6744-4365-8915-fc62f9f5369e"; internal const string DiscountId = "639a283d-790f-4f1a-b0df-de28d8796027"; private static HashSet<string>? creatureNames; internal static bool IsCreature(CardState card) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) if (card == null || (int)card.GetCardType() != 1) { return false; } if (creatureNames == null) { ? val = (JArray)JObject.Parse(File.ReadAllText(Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "json", "champions", "champion_vesper_beastmaster.json")))["beastmaster_creatures"]; creatureNames = new HashSet<string>(StringComparer.Ordinal); if ((int)val == 0) { val = new JArray(); } foreach (JObject item in (JArray)val) { string text = (string)item["card"]; string text2 = (string)item["mod"]; if (string.IsNullOrEmpty(text2)) { creatureNames.Add(text); creatureNames.Add("CardData_" + text); } else { creatureNames.Add(text2 + "-Card-" + text); } } } if (!creatureNames.Contains(card.GetAssetName())) { return creatureNames.Contains(card.GetCardDataID()); } return true; } internal static int GetLevel(CharacterState character, ICoreGameManagers managers) { if ((Object)(object)character == (Object)null || character.IsDead || character.HasStatusEffect("silenced") || character.HasStatusEffect("muted")) { return 0; } CardState spawnerCard = character.GetSpawnerCard(); for (int num = 3; num >= 1; num--) { string name = "mt2_freecompany.Plugin-Upgrade-upg_Beastmaster" + num; CardUpgradeData val = ((IEnumerable<CardUpgradeData>)managers.GetAllGameData().GetAllCardUpgradeData()).FirstOrDefault((Func<CardUpgradeData, bool>)((CardUpgradeData u) => (Object)(object)u != (Object)null && ((Object)u).name == name)); if ((Object)(object)val != (Object)null && (character.HasUpgrade(val) || (spawnerCard != null && spawnerCard.HasUpgrade(val)))) { return num; } } return 0; } private static List<int> GetLevels(ICoreGameManagers managers) { List<CharacterState> list = new List<CharacterState>(); managers.GetMonsterManager().AddCharactersToList(list); return (from c in list select GetLevel(c, managers) into l where l > 0 select l).ToList(); } internal static bool HasBeastmasterInRun(ICoreGameManagers managers) { string vesperName = "mt2_freecompany.Plugin-Card-SpawnVesper"; CardState[] array = (from card in managers.GetSaveManager().GetDeckState() where card != null && card.GetAssetName() == vesperName select card).ToArray(); if (array.Length != 0) { CardUpgradeData[] paths = (from u in managers.GetAllGameData().GetAllCardUpgradeData() where (Object)(object)u != (Object)null && Enumerable.Range(1, 3).Any((int level) => ((Object)u).name == "mt2_freecompany.Plugin-Upgrade-upg_Beastmaster" + level) select u).ToArray(); if (array.Any((CardState card) => paths.Any((CardUpgradeData path) => card.HasUpgrade(path)))) { return true; } } List<CharacterState> list = new List<CharacterState>(); managers.GetMonsterManager().AddCharactersToList(list); return list.Any(delegate(CharacterState character) { if ((Object)(object)character != (Object)null) { CardState spawnerCard = character.GetSpawnerCard(); if (((spawnerCard != null) ? spawnerCard.GetAssetName() : null) == vesperName) { return GetLevel(character, managers) > 0; } } return false; }); } internal static void Freeze(CardState card, ICoreGameManagers managers) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown if (!managers.GetSaveManager().PreviewMode && IsCreature(card) && GetLevels(managers).Count != 0) { Tame(card, managers); if (!card.HasTrait(typeof(CardTraitFreeze))) { CardTraitData val = new CardTraitData(); val.Setup("CardTraitFreeze"); managers.GetCardManager().AddTemporaryTraitToCard(card, val, true, false, true); } } } internal static void TrainHand(ICoreGameManagers managers) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown SaveManager saveManager = managers.GetSaveManager(); if (saveManager.PreviewMode) { return; } List<int> levels = GetLevels(managers); if (levels.Count == 0) { return; } CardState[] array = managers.GetCardManager().GetHand(false).ToArray(); foreach (CardState val in array) { if (IsCreature(val)) { Tame(val, managers); CardUpgradeState val2 = ((IEnumerable<CardUpgradeState>)val.GetTemporaryCardStateModifiers().GetCardUpgrades()).FirstOrDefault((Func<CardUpgradeState, bool>)((CardUpgradeState u) => u.GetCardUpgradeDataId() == "639a283d-790f-4f1a-b0df-de28d8796027")); CardUpgradeState val3 = new CardUpgradeState(); val3.Setup(); val3.SetCardUpgradeDataId("639a283d-790f-4f1a-b0df-de28d8796027"); val3.SetIsUnique(true); val3.SetCostReduction(levels.Count + ((val2 != null) ? val2.GetCostReduction() : 0)); if (val2 != null) { val.RemoveUpgrade(val2, val.GetTemporaryCardStateModifiers(), (string)null); } val.ApplyTemporaryUpgrade(val3, saveManager, (string)null); val.UpdateCardBodyText((SaveManager)null); managers.GetCardManager().RefreshCardInHand(val, false, false, false); } } } internal static void Tame(CardState card, ICoreGameManagers managers) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown SaveManager saveManager = managers.GetSaveManager(); if (!saveManager.PreviewMode && IsCreature(card) && GetLevels(managers).Count != 0 && !card.GetCardStateModifiers().GetCardUpgrades().Any((CardUpgradeState u) => u.GetCardUpgradeDataId() == "bde5128c-6744-4365-8915-fc62f9f5369e")) { CardUpgradeState val = new CardUpgradeState(); val.Setup(); val.SetCardUpgradeDataId("bde5128c-6744-4365-8915-fc62f9f5369e"); val.SetIsUnique(true); card.ApplyPermanentUpgrade(val, saveManager, true, (string)null); } } internal static IEnumerator TrainDeployed(ICoreGameManagers managers) { if (managers.GetSaveManager().PreviewMode || GetLevels(managers).Count == 0) { yield break; } List<CharacterState> list = new List<CharacterState>(); managers.GetMonsterManager().AddCharactersToList(list); foreach (CharacterState item in list) { if (!((Object)(object)item == (Object)null) && !item.IsDead && item.GetHP() > 0) { CardState spawnerCard = item.GetSpawnerCard(); if (spawnerCard != null && IsCreature(spawnerCard)) { Tame(spawnerCard, managers); BeastmasterMarkers.MarkTrained(item); } } } } internal static void RecallTroll(ICoreGameManagers managers) { if (managers.GetSaveManager().PreviewMode || GetLevels(managers).Count == 0) { return; } CardManager cardManager = managers.GetCardManager(); string value = "mt2_freecompany.Plugin-Card-Spawn"; CardState[] array = cardManager.GetHand(false).Concat(cardManager.GetDrawPile(false)).ToArray(); foreach (CardState val in array) { if (val.GetAssetName().StartsWith(value, StringComparison.Ordinal) && IsCreature(val)) { if (cardManager.GetHand(false).Contains(val) || cardManager.DrawSpecificCard(val, false, (DrawSource)0, (CardState)null, 1, 1)) { Freeze(val, managers); } break; } } } private static IEnumerator BeforeTurn(IEnumerator original) { AllGameManagers instance = AllGameManagers.Instance; ICoreGameManagers val = ((instance != null) ? instance.GetCoreManagers() : null); if (val != null) { TrainHand(val); yield return TrainDeployed(val); } while (original.MoveNext()) { yield return original.Current; } } } public sealed class CardEffectBeastmasterRecall : CardEffectBase { public override bool CanApplyInPreviewMode => false; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override bool TestEffect(CardEffectState state, CardEffectParams parameters, ICoreGameManagers managers) { return true; } public override IEnumerator ApplyEffect(CardEffectState state, CardEffectParams parameters, ICoreGameManagers managers, ISystemManagers systems) { BeastmasterTraining.RecallTroll(managers); yield break; } } [HarmonyPatch(typeof(CardUpgradeState), "LoadFromFile")] internal static class BeastmasterSavedUpgradePatch { internal static void Prefix(CardUpgradeState __instance, AllGameData allGameData) { string cardUpgradeDataId = __instance.GetCardUpgradeDataId(); string text = ((cardUpgradeDataId == "mt2_freecompany.BeastmasterTraining") ? "bde5128c-6744-4365-8915-fc62f9f5369e" : ((cardUpgradeDataId == "mt2_freecompany.BeastmasterDiscount") ? "639a283d-790f-4f1a-b0df-de28d8796027" : null)); if (text != null && (Object)(object)allGameData.FindCardUpgradeData(text) != (Object)null) { __instance.SetCardUpgradeDataId(text); } } } public sealed class CardEffectBeastmasterCommand : CardEffectAttackWithUnit { internal static bool Eligible(CharacterState unit) { if ((Object)(object)unit == (Object)null || unit.IsDead || !unit.CheckAttackConditions() || !unit.HasStatusEffect("mt2_freecompany.plugin_tamed")) { return false; } CardState spawnerCard = unit.GetSpawnerCard(); RoomState currentRoom = unit.GetCurrentRoom(false); if (spawnerCard != null && BeastmasterTraining.IsCreature(spawnerCard) && (Object)(object)currentRoom != (Object)null) { return currentRoom.GetNumCharacters((Type)1, true) > 0; } return false; } public override bool TestEffect(CardEffectState effect, CardEffectParams parameters, ICoreGameManagers managers) { if (parameters.targets != null && parameters.targets.Count > 0) { if (parameters.targets.Count == 1) { return Eligible(parameters.targets[0]); } return false; } List<CharacterState> list = new List<CharacterState>(); managers.GetMonsterManager().AddCharactersToList(list); return list.Any(Eligible); } } public sealed class CardEffectCleanseRandomDebuffed : CardEffectBase { public override bool CanApplyInPreviewMode => true; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override bool TestEffect(CardEffectState effect, CardEffectParams p, ICoreGameManagers g) { return true; } internal static bool Eligible(CharacterState unit) { if ((Object)(object)unit == (Object)null || !unit.IsAlive || unit.IsDestroyed || unit.HasStatusEffect("untouchable")) { return false; } List<StatusEffectStack> source = new List<StatusEffectStack>(); unit.GetStatusEffects(ref source, false); return source.Any((StatusEffectStack s) => s.Count > 0 && !s.State.IsHidden() && (int)s.State.GetDisplayCategory() == 1); } public override IEnumerator ApplyEffect(CardEffectState effect, CardEffectParams p, ICoreGameManagers g, ISystemManagers systems) { if (g.GetSaveManager().PreviewMode) { yield break; } List<CharacterState> list = new List<CharacterState>(); if (effect.GetParamBool2()) { g.GetMonsterManager().AddCharactersToList(list); } else { list.AddRange(p.targets); } list = list.Where((CharacterState u) => Eligible(u) && !u.PreviewMode).Distinct().ToList(); if (list.Count != 0) { CharacterState item = list[RandomManager.Range(0, list.Count, (RngId)6)]; List<CharacterState> original = p.targets; p.targets = new List<CharacterState> { item }; try { yield return ((CardEffectBase)new CardEffectRemoveAllStatusEffects()).ApplyEffect(effect, p, g, systems); } finally { p.targets = original; } } } } public sealed class CardEffectConsumeFromHand : CardEffectBase { public override bool CanApplyInPreviewMode => false; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override bool TestEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers) { return true; } public override IEnumerator ApplyEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers, ISystemManagers sysManagers) { CardPool pool = cardEffectState.GetParamCardPool(); if ((Object)(object)pool == (Object)null) { Log("ConsumeFromHand: falta param_card_pool."); yield break; } CardManager cardManager = coreGameManagers.GetCardManager(); if ((Object)(object)cardManager == (Object)null) { Log("ConsumeFromHand: no hay CardManager."); yield break; } bool incluirJugada = cardEffectState.GetParamBool(); CardState jugada = cardEffectParams.playedCard; List<CardState> hand = cardManager.GetHand(true); int consumidas = 0; foreach (CardState item in hand) { if (item == null || (item == jugada && !incluirJugada)) { continue; } string cardDataID = item.GetCardDataID(); if (!string.IsNullOrEmpty(cardDataID) && pool.Contains(cardDataID) && cardManager.IsCardInHand(item)) { DiscardCardParams val = new DiscardCardParams { discardCard = item, wasPlayed = false }; IEnumerator consumir = cardManager.ConsumeCardWithoutPlaying(val); while (consumir.MoveNext()) { yield return consumir.Current; } consumidas++; } } Log($"ConsumeFromHand: consumidas {consumidas} cartas de la mano (jugada incluida: {incluirJugada})."); } private static void Log(string mensaje) { Plugin.Logger.LogInfo((object)mensaje); } } public sealed class CardEffectGrantOnce : CardEffectBase { public override bool CanApplyInPreviewMode => false; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override bool TestEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers) { return true; } public override IEnumerator ApplyEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers, ISystemManagers sysManagers) { CardPool paramCardPool = cardEffectState.GetParamCardPool(); if ((Object)(object)paramCardPool == (Object)null) { Log("GrantOnce: falta param_card_pool."); yield break; } SaveManager saveManager = coreGameManagers.GetSaveManager(); if ((Object)(object)saveManager == (Object)null) { Log("GrantOnce: no hay SaveManager."); yield break; } SubtypeData paramSubtype = cardEffectState.GetParamSubtype(); foreach (CardState item in saveManager.GetDeckState()) { if (item == null) { continue; } if (paramSubtype != null && !paramSubtype.IsNone) { CharacterData spawnCharacterData = item.GetSpawnCharacterData(); if ((Object)(object)spawnCharacterData == (Object)null) { continue; } foreach (SubtypeData subtype in spawnCharacterData.GetSubtypes()) { if (subtype != null && subtype.Key == paramSubtype.Key) { Log("GrantOnce: ya hay en el mazo una carta con el subtipo '" + paramSubtype.Key + "', no se da nada."); yield break; } } } else { string cardDataID = item.GetCardDataID(); if (!string.IsNullOrEmpty(cardDataID) && paramCardPool.Contains(cardDataID)) { Log("GrantOnce: '" + cardDataID + "' ya esta en el mazo, no se da otra."); yield break; } } } string paramStr = cardEffectState.GetParamStr(); if (string.IsNullOrEmpty(paramStr)) { Log("GrantOnce: falta param_str con el nombre del efecto interno."); yield break; } Type type = typeof(CardEffectBase).Assembly.GetType(paramStr); if (type == null) { Log("GrantOnce: no existe la clase '" + paramStr + "' en Assembly-CSharp."); yield break; } object? obj = Activator.CreateInstance(type); CardEffectBase val = (CardEffectBase)((obj is CardEffectBase) ? obj : null); if (val == null) { Log("GrantOnce: '" + paramStr + "' no es un CardEffectBase."); yield break; } val.Setup(cardEffectState); Log("GrantOnce: la carta no estaba en el mazo; ejecutando " + paramStr + "."); IEnumerator ejecutar = val.ApplyEffect(cardEffectState, cardEffectParams, coreGameManagers, sysManagers); while (ejecutar.MoveNext()) { yield return ejecutar.Current; } } private static void Log(string mensaje) { Plugin.Logger.LogInfo((object)mensaje); } } public sealed class CardEffectOfferRandomFromPool : CardEffectBase { public override bool CanApplyInPreviewMode => false; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override bool TestEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers) { return true; } public override IEnumerator ApplyEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers, ISystemManagers sysManagers) { CardPool paramCardPool = cardEffectState.GetParamCardPool(); if ((Object)(object)paramCardPool == (Object)null) { Log("OfferRandomFromPool: falta param_card_pool."); yield break; } CardManager cardManager = coreGameManagers.GetCardManager(); if ((Object)(object)cardManager == (Object)null) { Log("OfferRandomFromPool: no hay CardManager."); yield break; } SubtypeData paramSubtype = cardEffectState.GetParamSubtype(); if (paramSubtype != null && !paramSubtype.IsNone) { SaveManager saveManager = coreGameManagers.GetSaveManager(); if ((Object)(object)saveManager == (Object)null) { Log("OfferRandomFromPool: no hay SaveManager."); yield break; } foreach (CardState item in saveManager.GetDeckState()) { if (item == null) { continue; } CharacterData spawnCharacterData = item.GetSpawnCharacterData(); if ((Object)(object)spawnCharacterData == (Object)null) { continue; } foreach (SubtypeData subtype in spawnCharacterData.GetSubtypes()) { if (subtype != null && subtype.Key == paramSubtype.Key) { Log("OfferRandomFromPool: ya hay en el mazo una carta con el subtipo '" + paramSubtype.Key + "', no se ofrece nada."); yield break; } } } } int numCards = paramCardPool.GetNumCards(); if (numCards <= 0) { Log("OfferRandomFromPool: el pool esta vacio."); yield break; } int num = cardEffectState.GetParamInt(); if (num <= 0) { num = 1; } if (num > numCards) { num = numCards; } int num2 = cardManager.GetMaxHandSize() - cardManager.GetNumCardsInHand(); if (num2 <= 0) { Log("OfferRandomFromPool: la mano esta llena, no se ofrece nada."); yield break; } if (num > num2) { Log($"OfferRandomFromPool: solo caben {num2} cartas en la mano; se recorta la oferta."); num = num2; } List<int> list = new List<int>(numCards); for (int i = 0; i < numCards; i++) { list.Add(i); } for (int num3 = numCards - 1; num3 > 0; num3--) { int index = RandomManager.Range(0, num3 + 1, (RngId)6); int value = list[num3]; list[num3] = list[index]; list[index] = value; } List<string> list2 = new List<string>(); for (int j = 0; j < num; j++) { CardData cardAtIndex = paramCardPool.GetCardAtIndex(list[j]); if (!((Object)(object)cardAtIndex == (Object)null)) { cardManager.AddNewCard(cardAtIndex, (CardPile)3, false, false, (AddCardUpgradingInfo)null, true); list2.Add(((GameData)cardAtIndex).GetID()); } } Log(string.Format("OfferRandomFromPool: ofrecidas {0} de {1} cartas del pool a la mano: {2}.", list2.Count, numCards, string.Join(", ", list2))); } private static void Log(string mensaje) { Plugin.Logger.LogInfo((object)mensaje); } } public sealed class CardEffectRefreshAbilityOnKill : CardEffectBase { private sealed class Estado { public bool activacionEnCurso; public bool mato; } private static readonly ConditionalWeakTable<CharacterState, Estado> estados = new ConditionalWeakTable<CharacterState, Estado>(); private static readonly PropertyInfo? PropEstado = typeof(CharacterState).GetProperty("PrimaryStateInformation", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); public override bool CanApplyInPreviewMode => false; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override bool TestEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers) { return true; } public override IEnumerator ApplyEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers, ISystemManagers sysManagers) { int paramInt = cardEffectState.GetParamInt(); List<CharacterState> targets = cardEffectParams.targets; if (targets == null || targets.Count == 0) { Log($"RefreshAbilityOnKill[{paramInt}]: sin objetivo (target_mode tiene que ser self)."); yield break; } foreach (CharacterState item in targets) { if ((Object)(object)item == (Object)null || !item.HasUnitAbility()) { continue; } Estado orCreateValue = estados.GetOrCreateValue(item); switch (paramInt) { case 0: orCreateValue.activacionEnCurso = true; orCreateValue.mato = false; break; case 1: if (orCreateValue.activacionEnCurso || HabilidadResolviendose(item)) { orCreateValue.mato = true; Log("RefreshAbilityOnKill: muerte durante la habilidad; la recarga se quita al terminar."); } else { int num2 = QuitarRecarga(item); Log($"RefreshAbilityOnKill: muerte fuera de la habilidad; quitadas {num2} de recarga."); } break; case 2: if (orCreateValue.mato) { int num = QuitarRecarga(item); Log($"RefreshAbilityOnKill: la habilidad mato; quitadas {num} de recarga, lista otra vez."); } orCreateValue.activacionEnCurso = false; orCreateValue.mato = false; break; default: Log($"RefreshAbilityOnKill: param_int {paramInt} no es 0, 1 ni 2."); break; } } } private static int QuitarRecarga(CharacterState unidad) { int statusEffectStacks = unidad.GetStatusEffectStacks("cooldown"); if (statusEffectStacks > 0) { unidad.RemoveStatusEffect("cooldown", statusEffectStacks, true); } return statusEffectStacks; } private static bool HabilidadResolviendose(CharacterState unidad) { try { object obj = PropEstado?.GetValue(unidad); FieldInfo fieldInfo = obj?.GetType().GetField("isUnitAbilityResolving", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); bool flag = default(bool); int num; if (fieldInfo != null) { object value = fieldInfo.GetValue(obj); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static void Log(string mensaje) { Plugin.Logger.LogInfo((object)mensaje); } } public sealed class CardEffectRemoveRandomDebuff : CardEffectBase { public override bool CanApplyInPreviewMode => true; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override bool TestEffect(CardEffectState effect, CardEffectParams parameters, ICoreGameManagers managers) { if (parameters.targets != null) { return parameters.targets.Count > 0; } return false; } public override IEnumerator ApplyEffect(CardEffectState effect, CardEffectParams parameters, ICoreGameManagers managers, ISystemManagers systems) { if (managers.GetSaveManager().PreviewMode) { yield break; } foreach (CharacterState target in parameters.targets) { List<StatusEffectStack> source = new List<StatusEffectStack>(); target.GetStatusEffects(ref source, false); List<StatusEffectStack> list = source.Where((StatusEffectStack s) => s.Count > 0 && !s.State.IsHidden() && (int)s.State.GetDisplayCategory() == 1).ToList(); if (list.Count != 0) { StatusEffectStack val = list[RandomManager.Range(0, list.Count, (RngId)6)]; target.RemoveStatusEffect(val.State.GetStatusId(), val.Count, new RemoveStatusEffectParams { showNotification = true, sourceCardState = parameters.playedCard, sourceRelicState = parameters.sourceRelic }, false); target.GetCharacterUI().ShowEffectVFX(target, effect.GetAppliedVFX(), parameters.appliedVfxId, (EffectVfxReason)0); } } } } public sealed class CardEffectRequisition : CardEffectBase { private const string PluginGuid = "mt2_freecompany.Plugin"; private static readonly Dictionary<string, string[]> Escaleras = new Dictionary<string, string[]> { ["Sub_Warrior"] = new string[3] { "Buckler", "KiteShield", "BulwarkPlate" }, ["Sub_Barbarian"] = new string[3] { "NotchedAxe", "TwinAxes", "ReaversMaul" }, ["Sub_Rogue"] = new string[3] { "Lockpicks", "PoisonedDagger", "ThiefsMantle" }, ["Sub_Wizard"] = new string[3] { "ChalkCircle", "Grimoire", "ArchmagesStaff" }, ["Sub_Cleric"] = new string[3] { "Bandages", "HolySymbol", "Reliquary" }, ["Sub_Ranger"] = new string[3] { "Shortbow", "Longbow", "GreatBow" } }; public override bool CanPlayWhenHandFull => false; private static string NombreSubtipo(string rolId) { return "mt2_freecompany.Plugin-Subtype-" + rolId; } private static string NombreCarta(string cardId) { return "mt2_freecompany.Plugin-Card-" + cardId; } public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override bool TestEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers) { SaveManager saveManager = coreGameManagers.GetSaveManager(); if ((Object)(object)saveManager != (Object)null && saveManager.PreviewMode) { return false; } return true; } public override IEnumerator ApplyEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers, ISystemManagers sysManagers) { int num = cardEffectState.GetParamInt(); if (num < 1 || num > 3) { Log($"Requisition: param_int={num} fuera de 1..3; se usa 1."); num = 1; } SaveManager saveManager = coreGameManagers.GetSaveManager(); if ((Object)(object)saveManager != (Object)null && saveManager.PreviewMode) { yield break; } AllGameData allGameData = coreGameManagers.GetAllGameData(); CardManager cardManager = coreGameManagers.GetCardManager(); if ((Object)(object)allGameData == (Object)null || (Object)(object)cardManager == (Object)null) { Log("Requisition: falta AllGameData o CardManager."); yield break; } CharacterState val = null; List<CharacterState> targets = cardEffectParams.targets; if (targets != null && targets.Count > 0) { val = targets[0]; } if ((Object)(object)val == (Object)null) { Log("Requisition: no hay objetivo; revisa target_mode en el JSON."); yield break; } CardData val2 = FindKitData(val, num, coreGameManagers); if (!((Object)(object)val2 == (Object)null)) { if (cardManager.AddNewCard(val2, (CardPile)3, false, false, (AddCardUpgradingInfo)null, true) == null) { Log("Requisition: AddNewCard devolvio null para " + ((Object)val2).name + " (mano llena?)."); } else { Log($"Requisition: a la mano {((Object)val2).name} (escalon {num})."); } } } internal static CardData? FindKitData(CharacterState target, int tier, ICoreGameManagers managers) { if (managers.GetSaveManager().PreviewMode) { return null; } if (tier < 1 || tier > 3) { return null; } string text = null; foreach (KeyValuePair<string, string[]> escalera in Escaleras) { if (TieneSubtipo(target, escalera.Key)) { text = escalera.Value[tier - 1]; break; } } if (text == null) { List<string[]> list = new List<string[]>(Escaleras.Values); text = list[RandomManager.Range(0, list.Count, (RngId)6)][tier - 1]; Log("Requisition: no matching role (" + ListarSubtipos(target) + "); selected " + text + "."); } CardData? obj = BuscarCarta(managers.GetAllGameData(), text); if ((Object)(object)obj == (Object)null) { Log("Requisition: missing card " + NombreCarta(text) + "."); } return obj; } private static CardData? BuscarCarta(AllGameData gameData, string cardId) { string text = NombreCarta(cardId); foreach (CardData allCardDatum in gameData.GetAllCardData()) { if ((Object)(object)allCardDatum != (Object)null && ((Object)allCardDatum).name == text) { return allCardDatum; } } return null; } private static bool TieneSubtipo(CharacterState target, string rolId) { string text = NombreSubtipo(rolId); foreach (SubtypeData subtype in target.GetSubtypes()) { if (subtype != null && (subtype.Key == text || subtype.Key.EndsWith("-" + text, StringComparison.Ordinal))) { return true; } } return false; } private static string ListarSubtipos(CharacterState target) { List<string> list = new List<string>(); foreach (SubtypeData subtype in target.GetSubtypes()) { if (subtype != null) { list.Add(subtype.Key); } } if (list.Count != 0) { return string.Join(", ", list); } return "(ninguno)"; } private static void Log(string mensaje) { Plugin.Logger.LogInfo((object)mensaje); } } public sealed class CardEffectRingPyreDamage : CardEffectBase { private const int PorAnilloPorDefecto = 5; private const int TopePorDefecto = 8; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override string GetDescriptionAsTrait(CardEffectState cardEffectState) { AllGameManagers instance = AllGameManagers.Instance; SaveManager val = ((instance != null) ? instance.GetSaveManager() : null); if ((Object)(object)val == (Object)null) { return string.Empty; } int num = CalcularDano(cardEffectState, val.GetDisplayDistance()); return string.Format(LocalizationExtensions.Localize("mt2_freecompany.Plugin_SeverancePayCurrentPyreDamage", (ILocalizationParameterContext)null), num); } public override bool TestEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers) { return true; } public override IEnumerator ApplyEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers, ISystemManagers sysManagers) { SaveManager saveManager = coreGameManagers.GetSaveManager(); if ((Object)(object)saveManager == (Object)null) { Log("RingPyreDamage: no hay SaveManager."); } else { if (saveManager.PreviewMode) { yield break; } PlayerManager playerManager = coreGameManagers.GetPlayerManager(); if ((Object)(object)playerManager == (Object)null) { Log("RingPyreDamage: no hay PlayerManager."); yield break; } int displayDistance = saveManager.GetDisplayDistance(); int num = CalcularDano(cardEffectState, displayDistance); if (num <= 0) { Log($"RingPyreDamage: anillo {displayDistance}, dano {num} -> no se aplica nada."); yield break; } playerManager.AdjustTowerHP(-num, true); int num2 = cardEffectState.GetParamInt(); if (num2 <= 0) { num2 = 5; } int num3 = cardEffectState.GetAdditionalParamInt(); if (num3 <= 0) { num3 = 8; } Log($"RingPyreDamage: anillo {displayDistance}, {num2} x ({num3} - {displayDistance}) = {num} de dano a la pira."); } } private static int CalcularDano(CardEffectState cardEffectState, int anillo) { int num = cardEffectState.GetParamInt(); if (num <= 0) { num = 5; } int num2 = cardEffectState.GetAdditionalParamInt(); if (num2 <= 0) { num2 = 8; } return Math.Max(0, num * (num2 - anillo)); } private static void Log(string mensaje) { Plugin.Logger.LogInfo((object)mensaje); } } internal static class RodericReinforcements { [HarmonyPatch(typeof(DeckScreen), "CollectCardsForSelection")] private static class SelectionCardsPatch { private static bool Prefix(DeckScreen __instance, ref List<CardState> __result) { if (!SelectionCards.TryGetValue(__instance, out List<CardState> value)) { return true; } __result = new List<CardState>(value); return false; } } [HarmonyPatch(typeof(CardManager), "SetupCards")] private static class BattleResetPatch { private static void Prefix() { DeadCards.Clear(); } } [HarmonyPatch(typeof(CardManager), "OnMonsterCardReturned")] private static class DeathReturnPatch { private static void Prefix(CardState cardState, CardPile cardPile, CharacterState characterState) { AllGameManagers instance = AllGameManagers.Instance; if (!((Object)(object)instance == (Object)null) && instance.AreMainSceneOnlyManagersInitialized() && !instance.GetCoreManagers().GetSaveManager().PreviewMode) { RecordReturn(cardState, characterState); } } } internal static readonly Dictionary<DeckScreen, List<CardState>> SelectionCards = new Dictionary<DeckScreen, List<CardState>>(); internal static readonly HashSet<CardState> DeadCards = new HashSet<CardState>(); internal static List<CardState> Candidates(CardManager cards, int maximumCost, out bool revive) { List<CardState> list = cards.GetHand(false).Concat(cards.GetDrawPile(false)).Concat(cards.GetDiscardPile(false)) .Where(Eligible) .Distinct() .ToList(); revive = list.Count == 0; if (revive) { list = (from c in cards.GetExhaustedPile(false).Concat(cards.GetEatenPile(false)) where DeadCards.Contains(c) && Eligible(c) select c).Distinct().ToList(); } return list; bool Eligible(CardState card) { if (card != null && card.IsMonsterCard() && !card.IsChampionCard() && (Object)(object)card.GetSpawnCharacterData() != (Object)null && card.GetCostWithoutAnyModifications() >= 0 && card.GetCostWithoutAnyModifications() <= maximumCost) { return !cards.IsCardInStandByPile(card); } return false; } } internal static void RecordReturn(CardState card, CharacterState character) { if ((Object)(object)character != (Object)null && (character.IsDead || character.GetHP() <= 0)) { DeadCards.Add(card); } } } public sealed class CardEffectRodericReinforcements : CardEffectBase, ICardEffectUiDialog, ICardEffect { public override bool CanApplyInPreviewMode => true; public override bool CanPlayAfterBossDead => false; public ScreenName RequiredScreenName => (ScreenName)3; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } private static CharacterState? Owner(CardEffectParams parameters) { return parameters.characterThatActivatedAbility ?? parameters.selfTarget; } public override bool TestEffect(CardEffectState effect, CardEffectParams parameters, ICoreGameManagers managers) { CharacterState val = Owner(parameters); if ((Object)(object)val == (Object)null || val.IsDead) { return false; } RoomState currentRoom = val.GetCurrentRoom(false); if ((Object)(object)currentRoom == (Object)null || currentRoom.GetNumCharacters((Type)2, true) >= 7 || currentRoom.GetRemainingSpawnPointCount((Type)2) <= 0 || currentRoom.GetMonsterPoint(val.GetSpawnPoint(false).GetIndexInRoom() + 1) == null) { return false; } int maximumCost = Math.Max(1, Math.Min(3, effect.GetParamInt())); bool revive; return RodericReinforcements.Candidates(managers.GetCardManager(), maximumCost, out revive).Count > 0; } public override IEnumerator ApplyEffect(CardEffectState effect, CardEffectParams parameters, ICoreGameManagers managers, ISystemManagers systemManagers) { if (managers.GetSaveManager().PreviewMode || !((CardEffectBase)this).TestEffect(effect, parameters, managers)) { yield break; } CharacterState owner = Owner(parameters); RoomState room = owner.GetCurrentRoom(false); CardManager cards = managers.GetCardManager(); int maximumCost = Math.Max(1, Math.Min(3, effect.GetParamInt())); bool revive; List<CardState> candidates = RodericReinforcements.Candidates(cards, maximumCost, out revive); CardState card = null; bool selected = false; ScreenManager screens = systemManagers.GetScreenManager(); CardStateChosenDelegate val3 = default(CardStateChosenDelegate); screens.SetScreenActive((ScreenName)3, true, (ScreenActiveCallback)delegate(IScreen screen) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_00bd: Expected O, but got Unknown DeckScreen val = (DeckScreen)(object)((screen is DeckScreen) ? screen : null); if (val == null) { throw new InvalidOperationException("Call to Arms requires the native DeckScreen."); } RodericReinforcements.SelectionCards[val] = candidates; try { Params val2 = new Params { mode = (Mode)9, targetMode = (TargetMode)(revive ? 15 : 13), cardTypeFilter = (CardType)1, showCancel = false }; CardState parentCardState = effect.GetParentCardState(); val2.titleKey = ((parentCardState != null) ? parentCardState.GetTitleKey() : null) ?? string.Empty; val2.ignoreDefaultFilters = true; val2.excludeFilteredOutCards = true; val.Setup(val2); } finally { RodericReinforcements.SelectionCards.Remove(val); } CardStateChosenDelegate obj = val3; if (obj == null) { CardStateChosenDelegate val4 = delegate(CardState chosen) { card = chosen; selected = true; screens.SetScreenActive((ScreenName)3, false, (ScreenActiveCallback)null); }; CardStateChosenDelegate val5 = val4; val3 = val4; obj = val5; } val.AddDeckScreenCardStateChosenDelegate(obj); }); while (!selected) { yield return null; } if (card == null || !candidates.Contains(card) || !((CardEffectBase)this).TestEffect(effect, parameters, managers)) { yield break; } CharacterState spawned = null; SpawnPoint monsterPoint = room.GetMonsterPoint(owner.GetSpawnPoint(false).GetIndexInRoom() + 1); yield return managers.GetMonsterManager().CreateMonsterState(card.GetSpawnCharacterData(), card, owner.GetCurrentRoomIndex(), (Action<CharacterState>)delegate(CharacterState unit) { spawned = unit; }, (SpawnMode)3, monsterPoint, (Action<CharacterState>)null, false, (CharacterData)null, (List<string>)null, (AddStatusEffectParams)null, false, (Action<CharacterState>)delegate(CharacterState unit) { if (revive) { unit.SetHealth(1, Math.Max(1, unit.GetMaxHP())); unit.AddStatusEffect("undying", 1, CharacterState.defaultAddStatusEffectParams, (CharacterState)null, false, false, false, false, false); } }, true, parameters.playedCard); if ((Object)(object)spawned == (Object)null) { yield break; } cards.GetDrawPile(false).Remove(card); cards.GetDiscardPile(false).Remove(card); cards.GetExhaustedPile(false).Remove(card); cards.GetEatenPile(false).Remove(card); RodericReinforcements.DeadCards.Remove(card); List<CharacterState> list = new List<CharacterState>(); room.AddCharactersToList(list, (Type)3, false, true); foreach (CharacterState item in list) { if ((Object)(object)item != (Object)(object)spawned) { managers.GetCombatManager().QueueTrigger(item, (Trigger)20, (CharacterState)null, true, true, (FireTriggersData)null, 1, (CharacterTriggerState)null); } } yield return cards.DiscardCard(new DiscardCardParams { discardCard = card, wasPlayed = true, characterSummoned = spawned }, false); cards.SetCardIsDrawable(card, true); } } public sealed class CardEffectWatchtowerToggle : CardEffectBase { [HarmonyPatch(typeof(CharacterState), "ApplyCardUpgrade")] private static class ApplySniperPatch { private static void Prefix(CharacterState __instance, ref CardUpgradeState cardUpgradeState, TrainRoomAttachmentState sourceTrainRoomAttachment) { cardUpgradeState = PrepareApplication(__instance, cardUpgradeState, sourceTrainRoomAttachment); } } [HarmonyPatch(typeof(CharacterState), "RemoveCardUpgrade")] private static class RemoveSniperPatch { private static void Prefix(CharacterState __instance, ref CardUpgradeState cardUpgradeState, TrainRoomAttachmentState sourceTrainRoomAttachment) { cardUpgradeState = PrepareRemoval(__instance, cardUpgradeState, sourceTrainRoomAttachment); } } public override bool CanApplyInPreviewMode => true; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } internal static bool IsWatchtowerUpgrade(CardUpgradeData? u) { if ((Object)(object)u != (Object)null) { if (!((Object)u).name.EndsWith("WatchtowerRoomUpgrade", StringComparison.Ordinal)) { return ((Object)u).name.EndsWith("WatchtowerRoomOffUpgrade", StringComparison.Ordinal); } return true; } return false; } internal static TrainRoomAttachmentState? Find(RoomState room) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) TrainRoomAttachmentType[] array = (TrainRoomAttachmentType[])(object)new TrainRoomAttachmentType[2] { default(TrainRoomAttachmentType), (TrainRoomAttachmentType)1 }; TrainRoomAttachmentState val2 = default(TrainRoomAttachmentState); foreach (TrainRoomAttachmentType val in array) { if (room.TryGetFirstTrainRoomAttachment(ref val2, val) && val2.UpgradeStates.Any<(CardUpgradeState, CardUpgradeData)>(((CardUpgradeState, CardUpgradeData) x) => IsWatchtowerUpgrade(x.Item2))) { return val2; } } return null; } private static bool Owns(TrainRoomAttachmentState? source, CardUpgradeState state) { if (source != null) { return source.UpgradeStates.Any<(CardUpgradeState, CardUpgradeData)>(((CardUpgradeState, CardUpgradeData) x) => IsWatchtowerUpgrade(x.Item2) && x.Item1.GetCardUpgradeDataId() == state.GetCardUpgradeDataId()); } return false; } private static CardUpgradeState WithoutSniper(CardUpgradeState source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown CardUpgradeState val = new CardUpgradeState(); val.Setup(source); val.GetStatusEffectUpgrades().RemoveAll((StatusEffectStackData s) => s.statusId == "sniper"); return val; } internal static CardUpgradeState PrepareApplication(CharacterState unit, CardUpgradeState state, TrainRoomAttachmentState? source) { if (!Owns(source, state) || !unit.HasStatusEffect("sniper")) { return state; } return WithoutSniper(state); } internal static CardUpgradeState PrepareRemoval(CharacterState unit, CardUpgradeState state, TrainRoomAttachmentState? source) { if (!Owns(source, state)) { return state; } CardUpgradeState applied = ((IEnumerable<CardUpgradeState>)unit.GetAppliedCardUpgrades()).FirstOrDefault((Func<CardUpgradeState, bool>)((CardUpgradeState x) => x.GetCardUpgradeDataId() == state.GetCardUpgradeDataId())); if (applied == null) { return state; } if (!unit.GetAppliedCardUpgrades().Any((CardUpgradeState x) => x != applied && x.GetStatusEffectUpgrades().Any((StatusEffectStackData s) => s.statusId == "sniper" && s.count > 0))) { return applied; } return WithoutSniper(applied); } public override bool TestEffect(CardEffectState e, CardEffectParams p, ICoreGameManagers g) { RoomState val = p.roomThatActivatedAbility ?? g.GetRoomManager().GetRoom(p.selectedRoom); if ((Object)(object)val != (Object)null) { return Find(val) != null; } return false; } public override IEnumerator ApplyEffect(CardEffectState e, CardEffectParams p, ICoreGameManagers g, ISystemManagers systems) { if (g.GetSaveManager().PreviewMode) { yield break; } RoomState room = p.roomThatActivatedAbility ?? g.GetRoomManager().GetRoom(p.selectedRoom); if ((Object)(object)room == (Object)null) { yield break; } TrainRoomAttachmentState a = Find(room); if (a == null) { yield break; } IReadOnlyList<(CardUpgradeState, CardUpgradeData)> upgradeStates = a.UpgradeStates; IList<(CardUpgradeState, CardUpgradeData)> upgrades = upgradeStates as IList<(CardUpgradeState, CardUpgradeData)>; if (upgrades == null) { yield break; } CardState cardState = a.CardState; CardEffectState? obj = ((cardState != null) ? ((IEnumerable<CardEffectState>)cardState.GetEffectStates()).FirstOrDefault((Func<CardEffectState, bool>)((CardEffectState x) => x.GetCardEffect() is CardEffectAttachTrainRoomAttachment && IsWatchtowerUpgrade(x.GetParamCardUpgradeData()))) : null); CardUpgradeData val = ((obj != null) ? obj.GetParamCardUpgradeData() : null); CardUpgradeData paramCardUpgradeData = e.GetParamCardUpgradeData(); if ((Object)(object)val == (Object)null || (Object)(object)paramCardUpgradeData == (Object)null) { yield break; } int index = -1; for (int num = 0; num < upgrades.Count; num++) { if (IsWatchtowerUpgrade(upgrades[num].Item2)) { index = num; break; } } if (index < 0) { yield break; } (CardUpgradeState, CardUpgradeData) old = upgrades[index]; CardUpgradeData nextData = (((Object)(object)old.Item2 == (Object)(object)val) ? paramCardUpgradeData : val); CardUpgradeState next = new CardUpgradeState(); next.Setup(nextData, false, false); List<CharacterState> impacted = a.CharactersImpacted.ToList(); foreach (CharacterState item in impacted) { yield return item.RemoveCardUpgrade(old.Item1, a.Guid, false, a); } upgrades[index] = (next, nextData); foreach (CharacterState item2 in impacted) { yield return item2.ApplyCardUpgrade(next, false, a.Guid, false, false, (CardState)null, (Action<UpgradeApplicationResult>)null, a, false); } yield return room.UpdateTrainRoomAttachments(); } } public sealed class CardEffectWidowsPension : CardEffectBase { public override bool CanApplyInPreviewMode => false; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override bool TestEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers) { return true; } public override IEnumerator ApplyEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers, ISystemManagers sysManagers) { int multiplo = cardEffectState.GetParamInt(); if (multiplo <= 0) { multiplo = 5; } PlayerManager jugador = coreGameManagers.GetPlayerManager(); List<CharacterState> targets = cardEffectParams.targets; if ((Object)(object)jugador == (Object)null || targets == null) { yield break; } foreach (CharacterState item in targets) { if ((Object)(object)item == (Object)null) { continue; } string detalle; int num = Calcular(item, multiplo, out detalle); Log($"WidowsPension: {item} -> {num} de oro ({detalle})."); if (num > 0) { IEnumerator pago = jugador.AdjustGold(num, true); while (pago.MoveNext()) { yield return pago.Current; } } } } private static int Calcular(CharacterState unidad, int multiplo, out string detalle) { CardState spawnerCard = unidad.GetSpawnerCard(); CharacterData val = ((spawnerCard != null) ? spawnerCard.GetSpawnCharacterData() : null) ?? unidad.GetSourceCharacterData(); if ((Object)(object)val == (Object)null) { detalle = "sin carta ni datos de personaje"; return 0; } int num = val.GetAttackDamage(); int num2 = val.GetHealth(); CardStateModifiers val2 = ((spawnerCard != null) ? spawnerCard.GetCardStateModifiers() : null); if (val2 != null) { num = CardStateModifiers.GetUpgradedStatValue(num, (StatType)0, (CardStateModifiers[])(object)new CardStateModifiers[1] { val2 }); num2 = CardStateModifiers.GetUpgradedStatValue(num2, (StatType)1, (CardStateModifiers[])(object)new CardStateModifiers[1] { val2 }); } int num3 = Math.Max(0, num) + Math.Max(0, num2); int result = (int)Math.Round((double)num3 / (double)multiplo, MidpointRounding.AwayFromZero) * multiplo; detalle = $"ataque {num} + vida {num2} = {num3}, redondeo a {multiplo}"; return result; } private static void Log(string mensaje) { Plugin.Logger.LogInfo((object)mensaje); } } [HarmonyPatch(typeof(CardState), "GetCardTypeCardText")] internal static class ChampionCardTypeLabel { private static void Postfix(CardState __instance, ref string outCardText) { string assetName = __instance.GetAssetName(); if (!(assetName != "mt2_freecompany.Plugin-Card-SpawnRoderic") || !(assetName != "mt2_freecompany.Plugin-Card-SpawnVesper")) { CharacterData spawnCharacterData = __instance.GetSpawnCharacterData(); SubtypeData? obj = ((spawnCharacterData != null) ? ((IEnumerable<SubtypeData>)spawnCharacterData.GetSubtypes()).FirstOrDefault((Func<SubtypeData, bool>)((SubtypeData subtype) => subtype != null && subtype.IsChampion)) : null); string text = ((obj != null) ? obj.LocalizedName : null); if (!string.IsNullOrEmpty(text)) { outCardText = text; } } } } internal static class ChampionSpriteVisuals { [HarmonyPatch] private static class PrefabPatch { private static bool Prepare() { if (Finalizer != null) { return AccessTools.Method(Finalizer, "CreateCharacterWithFrameAnimations", (Type[])null, (Type[])null) != null; } return false; } private static MethodBase TargetMethod() { return AccessTools.Method(Finalizer, "CreateCharacterWithFrameAnimations", (Type[])null, (Type[])null); } private static void Postfix(GameObject original, string name) { if (ArtName(name) || ArtName(((Object)original).name)) { Transform val = original.transform.Find("CharacterScale/CharacterUI"); SpriteRenderer val2 = default(SpriteRenderer); if ((Object)(object)val != (Object)null && ((Component)val).TryGetComponent<SpriteRenderer>(ref val2)) { ((Renderer)val2).enabled = false; } } } } [HarmonyPatch] private static class AwakePatch { private static bool Prepare() { if (Animated != null) { return AccessTools.Method(Animated, "Awake", (Type[])null, (Type[])null) != null; } return false; } private static MethodBase TargetMethod() { return AccessTools.Method(Animated, "Awake", (Type[])null, (Type[])null); } private static void Postfix(Component __instance) { if (Ours(__instance)) { CharacterUI componentInParent = __instance.GetComponentInParent<CharacterUI>(); SpriteRenderer val = (((Object)(object)componentInParent == (Object)null) ? null : ((Component)componentInParent).GetComponent<SpriteRenderer>()); if ((Object)(object)val != (Object)null) { ((Renderer)val).enabled = false; } } } } [HarmonyPatch] private static class BoundsPatch { private static bool Prepare() { if (Animated != null) { return AccessTools.Method(Animated, "Setup", (Type[])null, (Type[])null) != null; } return false; } private static MethodBase TargetMethod() { return AccessTools.Method(Animated, "Setup", (Type[])null, (Type[])null); } private static void Postfix(Component __instance, ref Bounds meshBounds) { //IL_003b: 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_0051: Unknown result type (might be due to invalid IL or missing references) if (!Ours(__instance)) { return; } MeshFilter component = __instance.GetComponent<MeshFilter>(); CharacterUI componentInParent = __instance.GetComponentInParent<CharacterUI>(); if ((Object)(object)((component != null) ? component.sharedMesh : null) != (Object)null && (Object)(object)componentInParent != (Object)null) { meshBounds = InParentSpace(component.sharedMesh.bounds, ((Component)component).transform, ((Component)componentInParent).transform); SpriteRenderer component2 = ((Component)componentInParent).GetComponent<SpriteRenderer>(); if ((Object)(object)component2 != (Object)null) { ((Renderer)component2).enabled = false; } } } } [HarmonyPatch(typeof(CharacterUI), "SetupAnchors")] private static class AnchorsPatch { private static void Postfix(CharacterUI __instance) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) Component? obj = Mesh(__instance); MeshFilter val = ((obj != null) ? obj.GetComponent<MeshFilter>() : null); Transform container; Vector3 c; if (!((Object)(object)obj == (Object)null) && !((Object)(object)((val != null) ? val.sharedMesh : null) == (Object)null)) { container = ((Component)__instance).transform.Find("VfxAnchors"); if (!((Object)(object)container == (Object)null)) { Bounds val2 = InParentSpace(val.sharedMesh.bounds, ((Component)val).transform, ((Component)__instance).transform); Vector3 min = ((Bounds)(ref val2)).min; Vector3 max = ((Bounds)(ref val2)).max; c = ((Bounds)(ref val2)).center; Place("VfxCenterAnchor", c.x, c.y); Place("VfxTopAnchor", c.x, max.y + 0.15f); Place("VfxBottomAnchor", c.x, min.y); float num = (float)AccessTools.Field(typeof(CharacterUI), "_facingDir").GetValue(__instance); float x = ((num < 0f) ? min.x : max.x); float x2 = ((num < 0f) ? max.x : min.x); Place("VfxSideFwdAnchor", x, c.y); Place("VfxSideBackAnchor", x2, c.y); Place("VfxSideFwdBottomAnchor", x, min.y); Place("VfxSideBackBottomAnchor", x2, min.y); } } void Place(string name, float num2, float y) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) Transform val3 = container.Find(name); if ((Object)(object)val3 != (Object)null) { val3.position = ((Component)__instance).transform.TransformPoint(new Vector3(num2, y, c.z)); } } } } private static readonly Type? Animated = AccessTools.TypeByName("TrainworksReloaded.Base.Prefab.CharacterUIMeshAnimatedSprite"); private static readonly Type? Finalizer = AccessTools.TypeByName("TrainworksReloaded.Base.Prefab.GameObjectCharacterArtFinalizer"); internal static bool ArtName(string name) { if (name.IndexOf("mt2_freecompany", StringComparison.OrdinalIgnoreCase) >= 0) { if (name.IndexOf("VesperCharacterArt", StringComparison.Ordinal) < 0) { return name.IndexOf("RodericCharacterArt", StringComparison.Ordinal) >= 0; } return true; } return false; } private static bool Ours(Component component) { Transform val = component.transform; while ((Object)(object)val != (Object)null) { if (ArtName(((Object)val).name)) { return true; } val = val.parent; } CharacterUI componentInParent = component.GetComponentInParent<CharacterUI>(); object obj; if (!((Object)(object)componentInParent == (Object)null)) { SpriteRenderer component2 = ((Component)componentInParent).GetComponent<SpriteRenderer>(); obj = ((component2 != null) ? component2.sprite : null); } else { obj = null; } Sprite val2 = (Sprite)obj; if ((Object)(object)val2 != (Object)null) { return ArtName(((Object)val2).name); } return false; } private static Component? Mesh(CharacterUI ui) { if (Animated == null) { return null; } Component componentInChildren = ((Component)ui).GetComponentInChildren(Animated, true); if (!((Object)(object)componentInChildren != (Object)null) || !Ours(componentInChildren)) { return null; } return componentInChildren; } internal static Bounds InParentSpace(Bounds b, Transform mesh, Transform parent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_004c: 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_005e: 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) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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) Bounds result = default(Bounds); ((Bounds)(ref result))..ctor(parent.InverseTransformPoint(mesh.TransformPoint(((Bounds)(ref b)).center)), Vector3.zero); Vector3 min = ((Bounds)(ref b)).min; Vector3 max = ((Bounds)(ref b)).max; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { for (int k = 0; k < 2; k++) { ((Bounds)(ref result)).Encapsulate(parent.InverseTransformPoint(mesh.TransformPoint(new Vector3((i == 0) ? min.x : max.x, (j == 0) ? min.y : max.y, (k == 0) ? min.z : max.z)))); } } } return result; } } internal static class Countdowns { internal sealed class Pendiente { public int dano; public CardState? carta; } internal sealed class PorUnidad { public readonly Dictionary<string, Pendiente> pendientes = new Dictionary<string, Pendiente>(); public readonly Dictionary<string, int> ultimoPiso = new Dictionary<string, int>(); } internal static readonly ConditionalWeakTable<CharacterState, PorUnidad> tabla = new ConditionalWeakTable<CharacterState, PorUnidad>(); internal static void Log(string mensaje) { Plugin.Logger.LogInfo((object)mensaje); } } public class CardEffectPlantCountdown : CardEffectDamage { private static bool avisoPrevia; public override IEnumerator ApplyEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers, ISystemManagers sysManagers) { int paramInt = cardEffectState.GetParamInt(); StatusEffectStackData[] paramStatusEffectStackData = cardEffectState.GetParamStatusEffectStackData(); if (paramStatusEffectStackData == null || paramStatusEffectStackData.Length == 0) { Countdowns.Log("PlantCountdown: falta param_status_effects."); yield break; } List<CharacterState> targets = cardEffectParams.targets; if (targets == null) { yield break; } foreach (CharacterState item in targets) { if ((Object)(object)item == (Object)null || item.IsDestroyed || !item.IsAlive) { continue; } StatusEffectStackData[] array; if (item.PreviewMode) { if (!avisoPrevia) { avisoPrevia = true; Countdowns.Log("PlantCountdown: [previa sin acumular] la vista previa pone el estado pero no apunta dano."); } array = paramStatusEffectStackData; foreach (StatusEffectStackData val in array) { if (val != null && !string.IsNullOrEmpty(val.statusId)) { item.AddStatusEffect(val.statusId, val.count, (CharacterState)null, true, false); } } continue; } Countdowns.PorUnidad orCreateValue = Countdowns.tabla.GetOrCreateValue(item); array = paramStatusEffectStackData; foreach (StatusEffectStackData val2 in array) { if (val2 == null || string.IsNullOrEmpty(val2.statusId)) { continue; } int statusEffectStacks = item.GetStatusEffectStacks(val2.statusId); if (statusEffectStacks <= 0) { orCreateValue.pendientes.Remove(val2.statusId); orCreateValue.ultimoPiso.Remove(val2.statusId); } item.AddStatusEffect(val2.statusId, val2.count, (CharacterState)null, true, false); if (item.GetStatusEffectStacks(val2.statusId) > statusEffectStacks) { if (!orCreateValue.pendientes.TryGetValue(val2.statusId, out Countdowns.Pendiente value)) { value = new Countdowns.Pendiente(); orCreateValue.pendientes[val2.statusId] = value; } value.dano += paramInt; value.carta = cardEffectParams.playedCard; orCreateValue.ultimoPiso[val2.statusId] = PisoDe(item); Countdowns.Log($"PlantCountdown: {val2.statusId} x{val2.count} en {item}, dano pendiente {value.dano}."); } } } } internal static int PisoDe(CharacterState unidad) { RoomState currentRoom = unidad.GetCurrentRoom(false); if (!((Object)(object)currentRoom != (Object)null)) { return -1; } return currentRoom.GetRoomIndex(); } } public sealed class CardEffectCountdownTick : CardEffectBase { public override bool CanApplyInPreviewMode => false; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override bool TestEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers) { return true; } public override IEnumerator ApplyEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers, ISystemManagers sysManagers) { StatusEffectStackData[] estados = cardEffectState.GetParamStatusEffectStackData(); List<CharacterState> targets = cardEffectParams.targets; if (estados == null || targets == null) { yield break; } foreach (CharacterState unidad in targets) { if ((Object)(object)unidad == (Object)null || unidad.IsDestroyed || !unidad.IsAlive) { continue; } Countdowns.PorUnidad info = Countdowns.tabla.GetOrCreateValue(unidad); int piso = CardEffectPlantCountdown.PisoDe(unidad); StatusEffectStackData[] array = estados; foreach (StatusEffectStackData val in array) { if (val == null || string.IsNullOrEmpty(val.statusId)) { continue; } int statusEffectStacks = unidad.GetStatusEffectStacks(val.statusId); if (statusEffectStacks <= 0) { info.pendientes.Remove(val.statusId); info.ultimoPiso.Remove(val.statusId); } else { if (info.ultimoPiso.TryGetValue(val.statusId, out var value) && value == piso) { continue; } info.ultimoPiso[val.statusId] = piso; unidad.RemoveStatusEffect(val.statusId, 1, true); Countdowns.Log($"CountdownTick: {val.statusId} {statusEffectStacks} -> {statusEffectStacks - 1} en {unidad} (piso {piso})."); if (statusEffectStacks - 1 > 0) { continue; } CardState playedCard = null; int num; if (info.pendientes.TryGetValue(val.statusId, out Countdowns.Pendiente value2)) { num = value2.dano; playedCard = value2.carta; info.pendientes.Remove(val.statusId); } else { num = ValorDelEstado(coreGameManagers, val.statusId); Countdowns.Log($"CountdownTick: sin dano apuntado para {val.statusId}; uso el param_int del estado, {num}."); } if (num > 0) { Countdowns.Log($"CountdownTick: {val.statusId} a 0, {num} de dano a {unidad}."); ApplyDamageToTargetParameters val2 = new ApplyDamageToTargetParameters { playedCard = playedCard, damageType = (Type)0 }; IEnumerator golpe = coreGameManagers.GetCombatManager().ApplyDamageToTarget(num, unidad, val2); while (golpe.MoveNext()) { yield return golpe.Current; } if ((Object)(object)unidad == (Object)null || unidad.IsDestroyed || !unidad.IsAlive) { break; } } } } } } private static int ValorDelEstado(ICoreGameManagers coreGameManagers, string statusId) { StatusEffectManager statusEffectManager = coreGameManagers.GetStatusEffectManager(); StatusEffectData val = ((statusEffectManager != null) ? statusEffectManager.GetStatusEffectDataById(statusId, true) : null); if (val == null) { return 0; } return val.GetParamInt(); } } public sealed class StatusEffectFreeCompanyCountdownState : StatusEffectState { public override bool TestTrigger(InputTriggerParams inputTriggerParams, OutputTriggerParams outputTriggerParams, ICoreGameManagers coreGameManagers) { return false; } public override int GetEffectMagnitude(int stacks = 1) { CharacterState associatedCharacter = ((StatusEffectState)this).GetAssociatedCharacter(); if ((Object)(object)associatedCharacter != (Object)null && Countdowns.tabla.TryGetValue(associatedCharacter, out Countdowns.PorUnidad value) && value.pendientes.TryGetValue(((StatusEffectState)this).GetStatusId(), out Countdowns.Pendiente value2)) { return value2.dano; } return ((StatusEffectState)this).GetParamInt(); } } public sealed class RelicEffectFieldForgeCost : RelicEffectBase, ICardModifierRelicEffect, IRelicEffect { private readonly RelicEffectModifyCardTypeCost native = new RelicEffectModifyCardTypeCost(); internal int CostModifier { get; private set; } public override PropDescriptions CreateEditorInspectorDescriptions() { return ((RelicEffectBase)native).CreateEditorInspectorDescriptions(); } public override void Initialize(RelicState state, RelicData data, RelicEffectData effect) { ((RelicEffectBase)this).Initialize(state, data, effect); CostModifier = effect.GetParamInt(); ((RelicEffectBase)native).Initialize(state, data, effect); } public bool ApplyCardStateModifiers(CardState card, RelicManager relics, SaveManager save, CardManager? cards) { return native.ApplyCardStateModifiers(card, relics, save, cards); } public bool GetTooltip(out string title, out string body) { return native.GetTooltip(ref title, ref body); } } [HarmonyPatch] internal static class FieldForgeMergeCost { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(EquipmentMergeRewardData), "GetStartingModifiersForChosenCards", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(CardEffectMergeEquipment), "OnMergeCardsChosen", (Type[])null, (Type[])null); } internal static int ComponentCost(CardState card, CardStatistics stats, MonsterManager? monsters, RelicManager? relics, RoomState? room) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 int num = 0; AllGameManagers instance = AllGameManagers.Instance; RelicManager val = ((instance != null) ? instance.GetRelicManager() : null); if ((int)card.GetCardType() == 7 && (Object)(object)val != (Object)null) { num = -val.GetRelicEffects<RelicEffectFieldForgeCost>(new List<RelicEffectFieldForgeCost>()).Sum((RelicEffectFieldForgeCost e) => e.CostModifier); } CardStateModifiers temporaryCardStateModifiers = card.GetTemporaryCardStateModifiers(); temporaryCardStateModifiers.IncrementAdditionalCost(num); try { return card.GetCost(stats, monsters, relics, room); } finally { temporaryCardStateModifiers.IncrementAdditionalCost(-num); } } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo getCost = AccessTools.Method(typeof(CardState), "GetCost", (Type[])null, (Type[])null); MethodInfo replacement = AccessTools.Method(typeof(FieldForgeMergeCost), "ComponentCost", (Type[])null, (Type[])null); int matches = 0; foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, getCost)) { instruction.opcode = OpCodes.Call; instruction.operand = replacement; int num = matches + 1; matches = num; } yield return instruction; } if (matches != 1) { throw new InvalidOperationException("Field Forge: merge cost call changed; expected one native GetCost call."); } } } [HarmonyPatch(typeof(CardManager), "PlayAnyCard")] internal static class FreeCompanyCardSounds { private static readonly HashSet<string> DamageCards = new HashSet<string>(StringComparer.Ordinal) { "MagicMissile", "Cloudkill", "DelayedBlastFireball", "FingerOfDeath", "Fireball", "LightningBolt", "BountyHunterShot", "HedgeMageVolley", "ShieldbearerAbility", "TwoHeadedWrath", "GrimoireMagicMissile1", "GrimoireMagicMissile2", "GrimoireMagicMissile3" }; private static readonly HashSet<string> HealCards = new HashSet<string>(StringComparer.Ordinal) { "CureWounds", "Resurrection", "BattleChaplainAbility" }; private static readonly HashSet<string> DebuffCards = new HashSet<string>(StringComparer.Ordinal) { "Banishment", "Fear", "Grease", "MassHoldPerson", "Silence", "Web", "DoubleShift" }; private static readonly HashSet<string> MoveCards = new HashSet<string>(StringComparer.Ordinal) { "DimensionDoor", "LongbowmanShiftAim" }; private static readonly HashSet<string> GoldCards = new HashSet<string>(StringComparer.Ordinal) { "SeverancePay", "CutpurseAbility" }; [HarmonyPostfix] private static void AfterPlay(CardState cardState, bool fromDirectPlay, bool __result) { if (__result && fromDirectPlay && cardState != null) { string text = "mt2_freecompany.Plugin-Card-"; string cardDataID = cardState.GetCardDataID(); if (cardDataID != null && cardDataID.StartsWith(text, StringComparison.Ordinal)) { string text2 = cardDataID.Substring(text.Length); string text3 = ((DamageCards.Contains(text2) || text2.StartsWith("RodericSlam", StringComparison.Ordinal)) ? "Combat_Attack" : (HealCards.Contains(text2) ? "Combat_Heal" : (DebuffCards.Contains(text2) ? "Combat_Debuff" : (MoveCards.Contains(text2) ? "Combat_Ascend" : (GoldCards.Contains(text2) ? "Node_Coins" : ((!cardState.IsMonsterCard()) ? "Combat_Buff" : "Combat_Spawn")))))); SoundManager.PlaySfxSignal.Dispatch(text3); } } } } public sealed class RelicEffectFirstUnitDiscountEachTurn : RelicEffectBase, ITurnPhaseStartOfPlayerTurnBeforeDrawRelicEffect, ITurnPhaseTimingRelicEffect, IRelicEffect, ITurnPhaseEndOfTurnRelicEffect, IOnCardAddedToHandRelicEffect, ICardPlayedRelicEffect { private readonly CardUpgradeState discount = new CardUpgradeState(); private bool available = true; public override PropDescriptions CreateEditorInspectorDescriptions() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown return new PropDescriptions(); } public override void Initialize(RelicState relicState, RelicData relicData, RelicEffectData relicEffectData) { ((RelicEffectBase)this).Initialize(relicState, relicData, relicEffectData); discount.Setup(); discount.SetIsUnique(true); discount.SetExcludeFromClones(true); discount.SetCardUpgradeDataId("mt2_freecompany.MarchingOrdersDiscount"); discount.SetRemoveOnDiscard(true); int num = Math.Max(0, relicEffectData.GetParamInt()); discount.SetCostReduction(num); discount.SetXCostReduction(num); available = true; } public bool TestEffectTurnPhaseTiming(RelicEffectParams relicEffectParams, ICoreGameManagers coreGameManagers) { return true; } public IEnumerator ApplyEffectTurnPhaseTiming(RelicEffectParams relicEffectParams, ICoreGameManagers coreGameManagers) { available = true; foreach (CardState item in coreGameManagers.GetCardManager().GetHand(false)) { ApplyDiscount(item); } yield break; } public bool OnCardAdded(CardAddedToHandRelicEffectParams relicEffectParams, ICoreGameManagers coreGameManagers) { if (available) { return ApplyDiscount(relicEffectParams.cardState); } return false; } public bool TestEffectOnCardPlayed(CardPlayedRelicEffectParams relicEffectParams, ICoreGameManagers coreGameManagers) { if (available) { return IsUnit(relicEffectParams.cardState); } return false; } public IEnumerator ApplyEffectOnCardPlayed(CardPlayedRelicEffectParams relicEffectParams, ICoreGameManagers coreGameManagers) { available = false; foreach (CardState item in coreGameManagers.GetCardManager().GetHand(false)) { if (item.GetTemporaryCardStateModifiers().HasUpgrade(discount)) { item.GetTemporaryCardStateModifiers().RemoveUpgrade(discount); item.UpdateCardBodyText((SaveManager)null); } } ((RelicEffectBase)this).NotifyRelicTriggered(coreGameManagers.GetRelicManager(), (CharacterUI)null, "", false, 0f); yield break; } public bool TestEffectEndOfTurn(EndOfTurnRelicEffectParams relicEffectParams, ICoreGameManagers coreGameManagers) { return true; } public IEnumerator ApplyEffectEndOfTurn(EndOfTurnRelicEffectParams relicEffectParams, ICoreGameManagers coreGameManagers) { available = true; yield break; } private static bool IsUnit(CardState? card) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 if (card != null) { return (int)card.GetCardType() == 1; } return false; } private bool ApplyDiscount(CardState? card) { if (!IsUnit(card) || card.GetTemporaryCardStateModifiers().HasUpgrade(discount)) { return false; } card.GetTemporaryCardStateModifiers().AddUpgrade(discount, (CardStateModifiers)null); card.UpdateCardBodyText((SaveManager)null); return true; } } internal static class RodericQuartermaster { private sealed class TurnUsage { internal int Turn = -1; internal bool Supplied; internal bool Salvaged; } [HarmonyPatch(typeof(CharacterState), "OnSpawn")] private static class SupplyPatch { private static void Postfix(CharacterState __instance, ref IEnumerator __result) { __result = BeforeSpawn(__instance, __result); } private static IEnumerator BeforeSpawn(CharacterState unit, IEnumerator original) { ICoreGameManagers val = LiveManagers(); if (val != null) { Supply(unit, val); } while (original.MoveNext()) { yield return original.Current; } } } [HarmonyPatch(typeof(CardManager), "CheckEquipmentRemoveFromStandByCondition")] private static class SalvagePatch { private static void Postfix(CharacterState character, CardState equipmentCard, ref CardPile __result) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected I4, but got Unknown ICoreGameManagers val = LiveManagers(); if (val != null) { __result = (CardPile)(int)Salvage(character, equipmentCard, __result, val); } } } [HarmonyPatch(typeof(CardManager), "SetupCards")] private static class BattleResetPatch { private static void Prefix() { ICoreGameManagers val = LiveManagers(); if (val == null || !val.GetSaveManager().PreviewMode) { Reset(); } } } [HarmonyPatch(typeof(CharacterTooltipHelper), "GetAdditionalTooltipContents")] private static class RulesTooltipPatch { private const string TooltipId = "mt2_freecompany.QuartermasterRules"; private static void Postfix(CharacterState characterState, SaveManager saveManager, ref IEnumerable<(TooltipContent content, bool allowDuplicates)> __result) { __result = AppendRules(__result, characterState, saveManager); } internal static IEnumerable<(TooltipContent content, bool allowDuplicates)> AppendRules(IEnumerable<(TooltipContent content, bool allowDuplicates)> original, CharacterState unit, SaveManager save) { bool shown = false; foreach (var item in original) { if (item.content.tooltipId == "mt2_freecompany.QuartermasterRules") { shown = true; } yield return item; } if (shown || (Object)(object)unit == (Object)null || (Object)(object)save == (Object)null) { yield break; } AllGameData allGameData = save.GetAllGameData(); if (!((Object)(object)allGameData == (Object)null)) { int level; CardUpgradeData val = FindUpgrade(unit, allGameData, out level); if (!((Object)(object)val == (Object)null)) { CardUpgradeState val2 = new CardUpgradeState(); val2.Setup(val, false, false); string text = LocalizationExtensions.Localize(val2.GetUpgradeDescriptionKey(), (ILocalizationParameterContext)new CardEffectLocalizationContext((ILocalizationEffectPower)(object)val, (CharacterState)null, unit.GetSpawnerCard(), (IRoomStateModifier)null, (CharacterStatusEffectAdjustments)null)); yield return (content: new TooltipContent(val2.GetUpgradeTitle(), text, (TooltipDesignType)8, "mt2_freecompany.QuartermasterRules", false, false), allowDuplicates: false); } } } } private static ConditionalWeakTable<CharacterState, TurnUsage> usage = new ConditionalWeakTable<CharacterState, TurnUsage>(); private static ConditionalWeakTable<CharacterState, object> salvagedUnits = new ConditionalWeakTable<CharacterState, object>(); internal static void Reset() { usage = new ConditionalWeakTable<CharacterState, TurnUsage>(); salvagedUnits = new ConditionalWeakTable<CharacterState, object>(); } internal static CardUpgradeData? FindUpgrade(CharacterState unit, AllGameData data, out int level) { level = 0; if ((Object)(object)unit == (Object)null) { return null; } CardState spawnerCard = unit.GetSpawnerCard(); if (spawnerCard == null || spawnerCard.GetAssetName() != "mt2_freecompany.Plugin-Card-SpawnRoderic") { return null; } for (int num = 3; num >= 1; num--) { string name = "mt2_freecompany.Plugin-Upgrade-upg_Quarter" + num; CardUpgradeData val = ((IEnumerable<CardUpgradeData>)data.GetAllCardUpgradeData()).FirstOrDefault((Func<CardUpgradeData, bool>)((CardUpgradeData u) => (Object)(object)u != (Object)null && ((Object)u).name == name)); if ((Object)(object)val != (Object)null && (unit.HasUpgrade(val) || spawnerCard.HasUpgrade(val))) { level = num; return val; } } return null; } private static IEnumerable<(CharacterState owner, int level)> Owners(ICoreGameManagers managers) { List<CharacterState> list = new List<CharacterState>(); managers.GetMonsterManager().AddCharactersToList(list); foreach (CharacterState item in list) { if (!((Object)(object)item == (Object)null) && !item.IsDestroyed && !item.IsDead && item.GetHP() > 0 && !item.HasStatusEffect("silenced") && !item.HasStatusEffect("muted") && (Object)(object)FindUpgrade(item, managers.GetAllGameData(), out var level) != (Object)null) { yield return (owner: item, level: level); } } } private static TurnUsage Usage(CharacterState owner, ICoreGameManagers managers) { TurnUsage value = usage.GetValue(owner, (