Decompiled source of FreeCompany v0.3.5

plugins/mt2_freecompany.Plugin.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.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, (