Decompiled source of FreeCompany v0.2.4

plugins/mt2_freecompany.Plugin.dll

Decompiled 10 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Configuration;
using TrainworksReloaded.Core;
using TrainworksReloaded.Core.Extensions;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("mt2_freecompany.Plugin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.4.0")]
[assembly: AssemblyInformationalVersion("0.2.4+dff5fb012995bde1d1cc97759d03cc3272576dc9")]
[assembly: AssemblyProduct("mt2_freecompany.Plugin")]
[assembly: AssemblyTitle("mt2_freecompany.Plugin")]
[assembly: AssemblyVersion("0.2.4.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
{
	public sealed class CardEffectAllRooms : CardEffectBase
	{
		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)
		{
			string paramStr = cardEffectState.GetParamStr();
			if (string.IsNullOrEmpty(paramStr))
			{
				Log("CardEffectAllRooms: falta param_str con el nombre del efecto interno.");
				yield break;
			}
			Type type = typeof(CardEffectBase).Assembly.GetType(paramStr);
			if (type == null)
			{
				Log("CardEffectAllRooms: 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("CardEffectAllRooms: '" + paramStr + "' no es un CardEffectBase.");
				yield break;
			}
			val.Setup(cardEffectState);
			List<CharacterState> list = new List<CharacterState>();
			coreGameManagers.GetMonsterManager().AddCharactersToList(list);
			List<CharacterState> list2 = new List<CharacterState>();
			foreach (CharacterState item in list)
			{
				if ((Object)(object)item != (Object)null && !item.IsDead)
				{
					list2.Add(item);
				}
			}
			if (list2.Count == 0)
			{
				Log("CardEffectAllRooms: no hay unidades vivas a las que aplicarlo.");
				yield break;
			}
			List<CharacterState> lista = cardEffectParams.targets;
			if (lista == null)
			{
				Log("CardEffectAllRooms: cardEffectParams.targets es null.");
				yield break;
			}
			List<CharacterState> previos = new List<CharacterState>(lista);
			lista.Clear();
			lista.AddRange(list2);
			Log($"CardEffectAllRooms: {paramStr} sobre {list2.Count} unidades de todos los pisos.");
			IEnumerator ejecutar = val.ApplyEffect(cardEffectState, cardEffectParams, coreGameManagers, sysManagers);
			while (ejecutar.MoveNext())
			{
				yield return ejecutar.Current;
			}
			lista.Clear();
			lista.AddRange(previos);
		}

		private static void Log(string mensaje)
		{
			Plugin.Logger.LogInfo((object)mensaje);
		}
	}
	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 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();
			bool flag = paramSubtype != null && !paramSubtype.IsNone;
			foreach (CardState item in saveManager.GetDeckState())
			{
				if (item == null)
				{
					continue;
				}
				if (flag)
				{
					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 CardEffectIfAllyHasUpgrade : CardEffectBase
	{
		private const string PluginGuid = "mt2_freecompany.Plugin";

		private static string NombreMejora(string upgradeId)
		{
			return "mt2_freecompany.Plugin-Upgrade-" + upgradeId;
		}

		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)
		{
			string paramStr = cardEffectState.GetParamStr();
			if (string.IsNullOrEmpty(paramStr))
			{
				Log("IfAllyHasUpgrade: falta param_str con el id de la mejora a buscar.");
				yield break;
			}
			CardUpgradeData val = BuscarMejora(coreGameManagers.GetAllGameData(), paramStr);
			if ((Object)(object)val == (Object)null)
			{
				Log("IfAllyHasUpgrade: NO ENCUENTRO la mejora " + NombreMejora(paramStr) + ".");
				yield break;
			}
			List<CharacterState> list = new List<CharacterState>();
			coreGameManagers.GetMonsterManager().AddCharactersToList(list);
			bool flag = false;
			foreach (CharacterState item in list)
			{
				if (!((Object)(object)item == (Object)null) && !item.IsDead)
				{
					if (item.HasUpgrade(val))
					{
						Log("IfAllyHasUpgrade: '" + item.GetName() + "' lleva '" + paramStr + "' en la unidad.");
						flag = true;
						break;
					}
					CardState spawnerCard = item.GetSpawnerCard();
					if (spawnerCard != null && spawnerCard.HasUpgrade(val))
					{
						Log("IfAllyHasUpgrade: '" + item.GetName() + "' lleva '" + paramStr + "' en la carta que la invoco.");
						flag = true;
						break;
					}
				}
			}
			if (!flag)
			{
				Log("IfAllyHasUpgrade: ningun aliado vivo lleva '" + paramStr + "' (ni en la unidad ni en su carta); no se aplica nada. Aliados vivos: " + ContarVivos(list) + ".");
			}
			else
			{
				CardEffectAddCardUpgradeToUnits val2 = new CardEffectAddCardUpgradeToUnits();
				((CardEffectBase)val2).Setup(cardEffectState);
				Log("IfAllyHasUpgrade: hay un aliado con '" + paramStr + "'; aplicando la mejora.");
				IEnumerator ejecutar = ((CardEffectBase)val2).ApplyEffect(cardEffectState, cardEffectParams, coreGameManagers, sysManagers);
				while (ejecutar.MoveNext())
				{
					yield return ejecutar.Current;
				}
			}
		}

		private static string ContarVivos(List<CharacterState> aliados)
		{
			int num = 0;
			List<string> list = new List<string>();
			foreach (CharacterState aliado in aliados)
			{
				if (!((Object)(object)aliado == (Object)null) && !aliado.IsDead)
				{
					num++;
					if (list.Count < 6)
					{
						list.Add(aliado.GetName() + ((aliado.GetSpawnerCard() == null) ? " (sin carta)" : ""));
					}
				}
			}
			return num + " -> " + string.Join(", ", list);
		}

		private static CardUpgradeData? BuscarMejora(AllGameData gameData, string upgradeId)
		{
			string text = NombreMejora(upgradeId);
			foreach (CardUpgradeData allCardUpgradeDatum in gameData.GetAllCardUpgradeData())
			{
				if ((Object)(object)allCardUpgradeDatum != (Object)null && ((Object)allCardUpgradeDatum).name == text)
				{
					return allCardUpgradeDatum;
				}
			}
			return null;
		}

		private static void Log(string mensaje)
		{
			Plugin.Logger.LogInfo((object)mensaje);
		}
	}
	public sealed class CardEffectIfSubtypeInDrawPile : CardEffectBase
	{
		private static readonly FieldInfo? ClavesDeSubtipo = typeof(CharacterData).GetField("subtypeKeys", BindingFlags.Instance | BindingFlags.NonPublic);

		private static bool? ultimoResultado;

		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)
		{
			SubtypeData paramSubtype = cardEffectState.GetParamSubtype();
			if (paramSubtype == null || paramSubtype.IsNone)
			{
				return Recordar(resultado: false, "falta param_subtype");
			}
			CardManager cardManager = coreGameManagers.GetCardManager();
			if ((Object)(object)cardManager == (Object)null)
			{
				return Recordar(resultado: false, "no hay CardManager");
			}
			string key = paramSubtype.Key;
			int num = Contar(cardManager.GetHand(false), key);
			if (num > 0)
			{
				return Recordar(resultado: true, $"{num} en la mano");
			}
			int num2 = Contar(cardManager.GetDrawPile(false), key);
			if (num2 > 0)
			{
				return Recordar(resultado: true, $"{num2} en la pila de robo");
			}
			int num3 = Contar(cardManager.GetDiscardPile(false), key);
			if (num3 > 0)
			{
				return Recordar(resultado: true, $"{num3} en el descarte");
			}
			return Recordar(resultado: false, "no hay ninguna en mano, robo ni descarte");
		}

		private static int Contar(List<CardState> pila, string buscado)
		{
			if (pila == null)
			{
				return 0;
			}
			int num = 0;
			foreach (CardState item in pila)
			{
				if (item == null)
				{
					continue;
				}
				CharacterData spawnCharacterData = item.GetSpawnCharacterData();
				if ((Object)(object)spawnCharacterData == (Object)null)
				{
					continue;
				}
				if (ClavesDeSubtipo?.GetValue(spawnCharacterData) is List<string> list)
				{
					foreach (string item2 in list)
					{
						if (item2 == buscado)
						{
							num++;
							break;
						}
					}
					continue;
				}
				foreach (SubtypeData subtype in spawnCharacterData.GetSubtypes())
				{
					if (subtype != null && subtype.Key == buscado)
					{
						num++;
						break;
					}
				}
			}
			return num;
		}

		private static bool Recordar(bool resultado, string motivo)
		{
			if (ultimoResultado != resultado)
			{
				ultimoResultado = resultado;
				Log("IfSubtypeInPiles: " + (resultado ? "SI" : "NO") + " se puede lanzar (" + motivo + ").");
			}
			return resultado;
		}

		public override IEnumerator ApplyEffect(CardEffectState cardEffectState, CardEffectParams cardEffectParams, ICoreGameManagers coreGameManagers, ISystemManagers sysManagers)
		{
			Log("IfSubtypeInPiles: guarda superada, sigue la cadena de efectos.");
			yield break;
		}

		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 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" }
		};

		private static readonly Random Azar = new Random();

		public override bool CanPlayWhenHandFull => false;

		private static string ClaveSubtipo(string rolId)
		{
			return "SubtytpesData_nameKey-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;
			}
			string text = null;
			foreach (KeyValuePair<string, string[]> escalera in Escaleras)
			{
				if (TieneSubtipo(val, escalera.Key))
				{
					text = escalera.Value[num - 1];
					break;
				}
			}
			if (text == null)
			{
				List<string[]> list = new List<string[]>(Escaleras.Values);
				text = list[Azar.Next(list.Count)][num - 1];
				Log("Requisition: objetivo sin subtipo de rol (vistos: " + ListarSubtipos(val) + "); al azar sale " + text + ".");
			}
			CardData val2 = BuscarCarta(allGameData, text);
			if ((Object)(object)val2 == (Object)null)
			{
				Log("Requisition: NO ENCUENTRO la carta " + NombreCarta(text) + ".");
			}
			else if (cardManager.AddNewCard(val2, (CardPile)3, false, false, (AddCardUpgradingInfo)null, true) == null)
			{
				Log("Requisition: AddNewCard devolvio null para " + text + " (mano llena?).");
			}
			else
			{
				Log($"Requisition: a la mano {text} (escalon {num}).");
			}
		}

		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 = ClaveSubtipo(rolId);
			foreach (SubtypeData subtype in target.GetSubtypes())
			{
				if (subtype != null && subtype.Key == text)
				{
					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 = 11;

		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 $"Pyre damage this Ring: <b>{num}</b>";
		}

		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 = 11;
				}
				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 = 11;
			}
			return Math.Max(0, num * (num2 - anillo));
		}

		private static void Log(string mensaje)
		{
			Plugin.Logger.LogInfo((object)mensaje);
		}
	}
	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);
		}
	}
	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))
					{
						item.AddStatusEffect(val2.statusId, val2.count, (CharacterState)null, true, false);
						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.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();
		}
	}
	[BepInPlugin("mt2_freecompany.Plugin", "mt2_freecompany.Plugin", "0.2.4")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger = new ManualLogSource("mt2_freecompany.Plugin");

		public void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Railhead.GetBuilder().Configure("mt2_freecompany.Plugin", (Action<IConfigurationBuilder>)delegate(IConfigurationBuilder c)
			{
				ConfigurationExtensions.AddMergedJsonFile(c, new List<string>(77)
				{
					"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_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"
				});
			});
			Logger.LogInfo((object)"Plugin mt2_freecompany.Plugin is loaded!");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "mt2_freecompany.Plugin";

		public const string PLUGIN_NAME = "mt2_freecompany.Plugin";

		public const string PLUGIN_VERSION = "0.2.4";
	}
}