Decompiled source of RoundWithBots v3.1.0

plugins/RoundsWithBots.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using CardChoiceSpawnUniqueCardPatch.CustomCategories;
using HarmonyLib;
using InControl;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using ModdingUtils.AIMinion;
using ModdingUtils.AIMinion.Extensions;
using ModdingUtils.GameModes;
using ModdingUtils.Utils;
using Photon.Pun;
using RWF;
using RWF.UI;
using RoundsWithBots.CardPickerAIs;
using RoundsWithBots.Extensions;
using RoundsWithBots.Menu;
using RoundsWithBots.Patches;
using RoundsWithBots.UI;
using RoundsWithBots.Utils;
using TMPro;
using UnboundLib;
using UnboundLib.Extensions;
using UnboundLib.GameModes;
using UnboundLib.Networking;
using UnboundLib.Utils;
using UnboundLib.Utils.UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 RoundsWithBots
{
	public class BotAIManager : MonoBehaviour, IPlayerPickStartHookHandler, IGameStartHookHandler, IPointStartHookHandler, IRoundEndHookHandler
	{
		internal static class StalemateHandler
		{
			public static bool IsStalemate => !PlayerManager.instance.players.Any((Player player) => !player.data.GetAdditionalData().IsBot && !CharacterDataExtension.GetAdditionalData(player.data).isAIMinion && PlayerStatus.PlayerAliveAndSimulated(player));

			public static IEnumerator HandleStalemate()
			{
				if (!PhotonNetwork.IsMasterClient && !PhotonNetwork.OfflineMode)
				{
					yield break;
				}
				yield return (object)new WaitForSeconds(2f);
				while (!IsStalemate)
				{
					yield return (object)new WaitForSeconds(0.5f);
				}
				yield return (object)new WaitForSeconds(RWBMenu.StalemateTimer.Value);
				while (IsStalemate)
				{
					yield return (object)new WaitForSeconds(RWBMenu.StalemateDamageCooldown.Value);
					Player[] array = PlayerManager.instance.players.Where((Player player) => PlayerStatus.PlayerAliveAndSimulated(player)).ToArray();
					if (array.Length == 0)
					{
						break;
					}
					Player val = array[Random.Range(0, array.Length)];
					NetworkingManager.RPC(typeof(StalemateHandler), "RPCA_SendTakeDamageOverTime", new object[4]
					{
						val.data.view.ControllerActorNr,
						val.playerID,
						val.data.maxHealth,
						RWBMenu.StalemateDamageDuration.Value
					});
				}
			}

			[UnboundRPC]
			public static void RPCA_SendTakeDamageOverTime(int actorID, int playerID, float damage, float duration)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: 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_0039: Unknown result type (might be due to invalid IL or missing references)
				Player playerWithActorAndPlayerIDs = FindPlayer.GetPlayerWithActorAndPlayerIDs(actorID, playerID);
				playerWithActorAndPlayerIDs.data.healthHandler.TakeDamageOverTime(damage * Vector2.down, Vector2.op_Implicit(((Component)playerWithActorAndPlayerIDs).gameObject.transform.position), duration, 0.5f, Color.white, (GameObject)null, (Player)null, true);
			}
		}

		public static BotAIManager Instance;

		public Dictionary<int, CardPickerAI> PickerAIs = new Dictionary<int, CardPickerAI>();

		private Coroutine stalemateHandlerCoroutine;

		private void Start()
		{
			InterfaceGameModeHooksManager.instance.RegisterHooks((object)this);
			Object.DontDestroyOnLoad((Object)(object)this);
			Instance = this;
		}

		public void SetBotsId()
		{
			LoggingUtils.Log("Getting bots player.");
			PickerAIs.Clear();
			List<int> list = (from player in PlayerManager.instance.players
				where player.data.GetAdditionalData().IsBot
				select player.playerID).ToList();
			PickerAIs = list.ToDictionary((int id) => id, (int id) => new CardPickerAI());
			list.ForEach(delegate(int id)
			{
				LoggingUtils.Log($"Bot '{id}' has been added to the list of bots id.");
			});
			LoggingUtils.Log("Successfully get list of bots player.");
		}

		public void OnPlayerPickStart()
		{
			((MonoBehaviour)this).StartCoroutine(Instance.AiPickCard());
		}

		public void OnGameStart()
		{
			Instance.SetBotsId();
			foreach (KeyValuePair<int, CardPickerAI> bot in PickerAIs)
			{
				((TMP_Text)((Component)((Component)PlayerManager.instance.players.First((Player p) => p.playerID == bot.Key)).GetComponentInChildren<PlayerName>()).GetComponent<TextMeshProUGUI>()).text = "<#07e0f0>[BOT]";
			}
		}

		public void OnPointStart()
		{
			if (stalemateHandlerCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(stalemateHandlerCoroutine);
			}
			stalemateHandlerCoroutine = ((MonoBehaviour)this).StartCoroutine(StalemateHandler.HandleStalemate());
		}

		public void OnRoundEnd()
		{
			int maxRounds = (int)GameModeManager.CurrentHandler.Settings["roundsToWinGame"];
			int? num = PlayerManager.instance.players.Select((Player p) => p.teamID).Distinct().Select((Func<int, int?>)((int id) => id))
				.FirstOrDefault((int? id) => GameModeManager.CurrentHandler.GetTeamScore(id.Value).rounds >= maxRounds);
			bool flag = PlayerManager.instance.players.All((Player p) => p.data.GetAdditionalData().IsBot || CharacterDataExtension.GetAdditionalData(p.data).isAIMinion);
			if (num.HasValue && flag)
			{
				((MonoBehaviour)this).StartCoroutine(Rematch());
			}
		}

		public IEnumerator Rematch()
		{
			yield return (object)new WaitForSeconds(1f);
			if (GameManager.instance.isPlaying)
			{
				RoundEndHandler.instance.OnGameOverChoose("REMATCH");
			}
		}

		public List<GameObject> GetSpawnCards()
		{
			LoggingUtils.Log("Getting spawn cards");
			return (List<GameObject>)AccessTools.Field(typeof(CardChoice), "spawnedCards").GetValue(CardChoice.instance);
		}

		public IEnumerator CycleThroughCards(float delay, List<GameObject> spawnedCards)
		{
			LoggingUtils.Log("Cycling through cards");
			CardInfo lastCardInfo = null;
			int index = 0;
			foreach (GameObject spawnedCard in spawnedCards)
			{
				CardInfo component = spawnedCard.GetComponent<CardInfo>();
				LoggingUtils.Log("Cycling through '$" + component.cardName + "' card");
				if ((Object)(object)lastCardInfo != (Object)null)
				{
					lastCardInfo.RPCA_ChangeSelected(false);
				}
				component.RPCA_ChangeSelected(true);
				AccessTools.Field(typeof(CardChoice), "currentlySelectedCard").SetValue(CardChoice.instance, index);
				lastCardInfo = component;
				index++;
				yield return (object)new WaitForSeconds(delay);
			}
			LoggingUtils.Log("Successfully gone through all cards");
		}

		public IEnumerator GoToCards(GameObject selectedCards, List<GameObject> spawnedCards, float delay)
		{
			LoggingUtils.Log($"Going to '${selectedCards}' card");
			int selectedCardIndex = spawnedCards.IndexOf(selectedCards);
			int handIndex = int.Parse(AccessTools.Field(typeof(CardChoice), "currentlySelectedCard").GetValue(CardChoice.instance).ToString());
			while (handIndex != selectedCardIndex)
			{
				CardInfo component = spawnedCards[handIndex].GetComponent<CardInfo>();
				component.RPCA_ChangeSelected(false);
				LoggingUtils.Log($"Currently on '${component}' card");
				if (handIndex > selectedCardIndex)
				{
					handIndex--;
				}
				else if (handIndex < selectedCardIndex)
				{
					handIndex++;
				}
				component = spawnedCards[handIndex].GetComponent<CardInfo>();
				component.RPCA_ChangeSelected(true);
				AccessTools.Field(typeof(CardChoice), "currentlySelectedCard").SetValue(CardChoice.instance, handIndex);
				yield return (object)new WaitForSeconds(delay);
			}
			LoggingUtils.Log($"Successfully got to '${selectedCards}' card");
		}

		public void PickCard(List<GameObject> spawnCards)
		{
			CardChoice.instance.Pick(spawnCards[(int)ExtensionMethods.GetFieldValue((object)CardChoice.instance, "currentlySelectedCard")], true);
		}

		public IEnumerator AiPickCard()
		{
			if (!PhotonNetwork.IsMasterClient && !PhotonNetwork.OfflineMode)
			{
				yield break;
			}
			yield return (object)new WaitUntil((Func<bool>)(() => CardChoice.instance.IsPicking && ((List<GameObject>)ExtensionMethods.GetFieldValue((object)CardChoice.instance, "spawnedCards")).Count == ((Transform[])ExtensionMethods.GetFieldValue((object)CardChoice.instance, "children")).Count() && !((List<GameObject>)ExtensionMethods.GetFieldValue((object)CardChoice.instance, "spawnedCards")).Any((GameObject card) => (Object)(object)card == (Object)null)));
			for (int i = 0; i < PlayerManager.instance.players.Count; i++)
			{
				_ = PlayerManager.instance.players[i];
				if (PickerAIs.ContainsKey(CardChoice.instance.pickrID))
				{
					LoggingUtils.Log("AI picking card");
					List<GameObject> spawnCards = GetSpawnCards();
					((Component)spawnCards[0].GetComponent<CardInfo>()).GetComponent<PhotonView>().RPC("RPCA_ChangeSelected", (RpcTarget)0, new object[1] { true });
					ICardPickerAI cardPickerAI = PickerAIs[CardChoice.instance.pickrID].cardPickerAI;
					StartCardsPicking(spawnCards, cardPickerAI, PickerAIs[CardChoice.instance.pickrID].pickerInfo);
					break;
				}
			}
		}

		public void StartCardsPicking(List<GameObject> spawnCards, ICardPickerAI botCardPickerAI, PickerInfo pickerInfo)
		{
			if (botCardPickerAI == null)
			{
				LoggingUtils.Log("Bot card picker AI is null, Skipping card picking");
				return;
			}
			List<CardInfo> list = spawnCards.Select((GameObject card) => card.GetComponent<CardInfo>()).ToList();
			List<CardInfo> list2 = botCardPickerAI.PickCard(list);
			CardInfo item = list2.ElementAt(Random.Range(0, list2.Count));
			int num = list.IndexOf(item);
			NetworkingManager.RPC(typeof(BotAIManager), "RPCA_PickCardsAtPosition", new object[5] { num, pickerInfo.CycleDelay, pickerInfo.PreCycleDelay, pickerInfo.GoToCardDelay, pickerInfo.PickDelay });
		}

		private IEnumerator PickCardsAtPosition(int position, float cycleDelay, float preCycleDelay, float goToCardDelay, float pickDelay)
		{
			List<GameObject> spawnCards = GetSpawnCards();
			yield return CycleThroughCards(cycleDelay, spawnCards);
			yield return (object)new WaitForSeconds(preCycleDelay);
			yield return GoToCards(spawnCards[position], spawnCards, goToCardDelay);
			yield return (object)new WaitForSeconds(pickDelay);
			PickCard(spawnCards);
		}

		[UnboundRPC]
		private static void RPCA_PickCardsAtPosition(int position, float cycleDelay, float preCycleDelay, float goToCardDelay, float pickDelay)
		{
			((MonoBehaviour)Instance).StartCoroutine(Instance.PickCardsAtPosition(position, cycleDelay, preCycleDelay, goToCardDelay, pickDelay));
		}
	}
	public class PickerInfo
	{
		public float CycleDelay;

		public float PreCycleDelay;

		public float GoToCardDelay;

		public float PickDelay;

		public PickerInfo(float cycleDelay, float preCycleDelay, float goToCardDelay, float pickDelay)
		{
			CycleDelay = cycleDelay;
			PreCycleDelay = preCycleDelay;
			GoToCardDelay = goToCardDelay;
			PickDelay = pickDelay;
		}

		public PickerInfo()
		{
			CycleDelay = RWBMenu.CycleDelay.Value;
			PreCycleDelay = RWBMenu.PreCycleDelay.Value;
			GoToCardDelay = RWBMenu.GoToCardDelay.Value;
			PickDelay = RWBMenu.PickDelay.Value;
		}
	}
	public class CardPickerAI
	{
		public ICardPickerAI cardPickerAI;

		public PickerInfo pickerInfo;

		public CardPickerAI(ICardPickerAI cardPickerAI, PickerInfo pickerInfo)
		{
			this.cardPickerAI = cardPickerAI;
			this.pickerInfo = pickerInfo;
		}

		public CardPickerAI()
		{
			cardPickerAI = new RarestCardPicker();
			pickerInfo = new PickerInfo();
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.aalund13.rounds.roundswithbots", "Rounds With Bots", "2.3.0")]
	[BepInProcess("Rounds.exe")]
	public class RoundsWithBots : BaseUnityPlugin
	{
		private const string ModId = "com.aalund13.rounds.roundswithbots";

		private const string ModName = "Rounds With Bots";

		public const string Version = "2.3.0";

		public const string ModInitials = "RWB";

		public bool IsPicking;

		public AssetBundle Assets;

		public static RoundsWithBots Instance { get; private set; }

		private void Awake()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Assets = AssetUtils.LoadAssetBundleFromResources("rwb_assets", typeof(RoundsWithBots).Assembly);
			new Harmony("com.aalund13.rounds.roundswithbots").PatchAll();
		}

		private void Start()
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			RWBMenu.RegisterMenu("Rounds With Bots", ((BaseUnityPlugin)this).Config);
			Unbound.RegisterHandshake("com.aalund13.rounds.roundswithbots", (Action)OnHandShakeCompleted);
			Cards.instance.AddCardValidationFunction((Func<Player, CardInfo, bool>)((Player player, CardInfo card) => (!((Behaviour)((Component)player).GetComponent<PlayerAPI>()).enabled || !card.blacklistedCategories.Contains(CustomCardCategories.instance.CardCategory("NotForBots"))) ? true : false));
			CardExclusiveUtils.ExcludeCardsFromBots(CardManager.GetCardInfoWithName("Remote"));
			CardExclusiveUtils.ExcludeCardsFromBots(CardManager.GetCardInfoWithName("Teleport"));
			CardExclusiveUtils.ExcludeCardsFromBots(CardManager.GetCardInfoWithName("Shield Charge"));
			BotAIManager.Instance = new GameObject("RWB_BotAIManager").AddComponent<BotAIManager>();
			Object.DontDestroyOnLoad((Object)(object)((Component)BotAIManager.Instance).gameObject);
		}

		private void OnHandShakeCompleted()
		{
			if (PhotonNetwork.IsMasterClient)
			{
				NetworkingManager.RPC_Others(((object)this).GetType(), "RPCA_SyncSettings", new object[7]
				{
					RWBMenu.StalemateTimer.Value,
					RWBMenu.StalemateDamageCooldown.Value,
					RWBMenu.StalemateDamageDuration.Value,
					RWBMenu.CycleDelay.Value,
					RWBMenu.PreCycleDelay.Value,
					RWBMenu.GoToCardDelay.Value,
					RWBMenu.PickDelay.Value
				});
			}
		}

		[UnboundRPC]
		private static void RPCA_SyncSettings(float stalemateTimer, float stalemateDamageCooldown, float stalemateDamageDuration, float cycleDelay, float preCycleDelay, float goToCardDelay, float pickDelay)
		{
			RWBMenu.StalemateTimer.Value = stalemateTimer;
			RWBMenu.StalemateDamageCooldown.Value = stalemateDamageCooldown;
			RWBMenu.StalemateDamageDuration.Value = stalemateDamageDuration;
			RWBMenu.CycleDelay.Value = cycleDelay;
			RWBMenu.PreCycleDelay.Value = preCycleDelay;
			RWBMenu.GoToCardDelay.Value = goToCardDelay;
			RWBMenu.PickDelay.Value = pickDelay;
		}
	}
}
namespace RoundsWithBots.Utils
{
	public class CardExclusiveUtils
	{
		public static CardCategory NotBotCategory = CustomCardCategories.instance.CardCategory("NotForBots");

		public static void ExcludeCardsFromBots(CardInfo card)
		{
			card.blacklistedCategories = CollectionExtensions.AddToArray<CardCategory>(card.blacklistedCategories, NotBotCategory);
		}
	}
	public static class EaseUtils
	{
		public enum EaseType
		{
			easeInSine,
			easeOutSine,
			easeInOutSine,
			easeInQuad,
			easeOutQuad,
			easeInOutQuad
		}

		public static float Ease(float time, float start, float end, float duration, EaseType easeType)
		{
			switch (easeType)
			{
			case EaseType.easeInSine:
				return 0f - Mathf.Cos(time / duration * ((float)Math.PI / 2f)) + 1f * (end - start) + start;
			case EaseType.easeOutSine:
				return Mathf.Sin(time / duration * ((float)Math.PI / 2f)) * (end - start) + start;
			case EaseType.easeInOutSine:
				return -0.5f * (Mathf.Cos((float)Math.PI * time / duration) - 1f) * (end - start) + start;
			case EaseType.easeInQuad:
				return (end - start) * (time /= duration) * time + start;
			case EaseType.easeOutQuad:
				return (0f - (end - start)) * (time /= duration) * (time - 2f) + start;
			case EaseType.easeInOutQuad:
				if (!((time /= duration / 2f) < 1f))
				{
					return (0f - (end - start)) / 2f * ((time -= 1f) * (time - 2f) - 1f) + start;
				}
				return (end - start) / 2f * time * time + start;
			default:
				return 0f;
			}
		}

		public static IEnumerator EaseCoroutine(float duration, EaseType easeType, Action<float> action, Action onComplete = null, float min = 0f, float max = 1f)
		{
			float time = 0f;
			while (time < duration)
			{
				action(Ease(time, min, max, duration, easeType));
				time += Time.deltaTime;
				yield return null;
			}
			action(Ease(duration, min, max, duration, easeType));
			onComplete?.Invoke();
		}
	}
	public static class LoggingUtils
	{
		public static void Log(string message)
		{
			if (RWBMenu.DebugMode.Value)
			{
				Debug.Log((object)message);
			}
		}

		public static void LogWarning(string message)
		{
			if (RWBMenu.DebugMode.Value)
			{
				Debug.LogWarning((object)message);
			}
		}

		public static void Error(string message)
		{
			if (RWBMenu.DebugMode.Value)
			{
				Debug.LogError((object)message);
			}
		}
	}
}
namespace RoundsWithBots.UI
{
	internal class BotMenuUIHandler : MonoBehaviour
	{
		public static GameObject Prefab;

		public static GameObject CurrentInstance;

		public GameObject MenuObject;

		public FaceSelectorUI faceSelectorUI;

		public TeamSelectorUI teamSelectorUI;

		private CharacterSelectionInstance characterSelectionInstance;

		private bool IsOpen => ((Component)this).GetComponent<CanvasGroup>().alpha == 1f;

		public void Update()
		{
			if (((Object)(object)characterSelectionInstance == (Object)null || (Object)(object)characterSelectionInstance.currentPlayer == (Object)null) && IsOpen)
			{
				Hide();
			}
		}

		public static BotMenuUIHandler Show(CharacterSelectionInstance characterSelectionInstance)
		{
			if ((Object)(object)CurrentInstance != (Object)null)
			{
				CurrentInstance.GetComponent<BotMenuUIHandler>().Hide();
			}
			CurrentInstance = CreateInstance(Prefab);
			BotMenuUIHandler component = CurrentInstance.GetComponent<BotMenuUIHandler>();
			component.characterSelectionInstance = characterSelectionInstance;
			component.faceSelectorUI.SetupForCharacterSelection(characterSelectionInstance);
			component.teamSelectorUI.SetupForCharacterSelection(characterSelectionInstance);
			((Component)component).GetComponent<CanvasGroup>().interactable = true;
			((MonoBehaviour)component).StartCoroutine(component.ToggleMenu(toggle: true));
			return component;
		}

		public void RemovePlayer()
		{
			PlayerManager.instance.RemovePlayer(characterSelectionInstance.currentPlayer);
		}

		public void Hide()
		{
			((MonoBehaviour)this).StartCoroutine(HideThenDestroy());
		}

		private IEnumerator HideThenDestroy()
		{
			((Component)this).GetComponent<CanvasGroup>().interactable = false;
			yield return ToggleMenu(toggle: false);
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}

		private IEnumerator ToggleMenu(bool toggle)
		{
			if (IsOpen != toggle)
			{
				float min = (toggle ? 0f : 1f);
				float max = (toggle ? 1f : 0f);
				yield return EaseUtils.EaseCoroutine(0.2f, EaseUtils.EaseType.easeInQuad, delegate(float value)
				{
					((Component)this).GetComponent<CanvasGroup>().alpha = value;
				}, null, min, max);
				((Component)this).GetComponent<CanvasGroup>().blocksRaycasts = toggle;
			}
		}

		private static GameObject CreateInstance(GameObject prefab)
		{
			GameObject obj = Object.Instantiate<GameObject>(prefab);
			Object.DontDestroyOnLoad((Object)(object)obj);
			GameObject gameObject = ((Component)obj.transform.GetChild(0)).gameObject;
			gameObject.GetComponent<CanvasGroup>().interactable = false;
			gameObject.GetComponent<CanvasGroup>().blocksRaycasts = false;
			gameObject.GetComponent<CanvasGroup>().alpha = 0f;
			return gameObject;
		}

		static BotMenuUIHandler()
		{
			AssetBundle assets = RoundsWithBots.Instance.Assets;
			Prefab = ((assets != null) ? assets.LoadAsset<GameObject>("BotMenu") : null);
		}
	}
	public class FaceSelectorUI : MonoBehaviour
	{
		internal CharacterSelectionInstance characterSelectionInstance;

		public TextMeshProUGUI faceText;

		public void SetupForCharacterSelection(CharacterSelectionInstance characterSelectionInstance)
		{
			this.characterSelectionInstance = characterSelectionInstance;
			UpdateText(characterSelectionInstance.currentlySelectedFace);
		}

		public void IncrementFaceIndex()
		{
			characterSelectionInstance.currentlySelectedFace = (characterSelectionInstance.currentlySelectedFace + 1 + 8) % 8;
			UpdateText(characterSelectionInstance.currentlySelectedFace);
		}

		public void DecrementFaceIndex()
		{
			characterSelectionInstance.currentlySelectedFace = (characterSelectionInstance.currentlySelectedFace - 1 + 8) % 8;
			UpdateText(characterSelectionInstance.currentlySelectedFace);
		}

		private void UpdateText(int selectedFace)
		{
			((TMP_Text)faceText).text = $"FACE: {selectedFace}";
		}
	}
	public class TeamSelectorUI : MonoBehaviour
	{
		internal CharacterSelectionInstance characterSelectionInstance;

		public TextMeshProUGUI teamText;

		public void SetupForCharacterSelection(CharacterSelectionInstance characterSelectionInstance)
		{
			this.characterSelectionInstance = characterSelectionInstance;
			UpdateText(PlayerExtensions.GetAdditionalData(characterSelectionInstance.currentPlayer).colorID);
		}

		public void IncrementTeamIndex()
		{
			int num = ChanageTeam(1);
			PlayerExtensions.AssignColorID(characterSelectionInstance.currentPlayer, num);
			characterSelectionInstance.currentPlayer.SetColors();
			CharacterSelectionInstancePatch.RequestColorChange[characterSelectionInstance] = true;
			UpdateText(num);
		}

		public void DecrementTeamIndex()
		{
			int num = ChanageTeam(-1);
			PlayerExtensions.AssignColorID(characterSelectionInstance.currentPlayer, num);
			characterSelectionInstance.currentPlayer.SetColors();
			CharacterSelectionInstancePatch.RequestColorChange[characterSelectionInstance] = true;
			UpdateText(num);
		}

		public int ChanageTeam(int colorIDDelta)
		{
			int num = (PlayerExtensions.GetAdditionalData(characterSelectionInstance.currentPlayer).colorID + colorIDDelta + RWFMod.MaxColorsHardLimit) % RWFMod.MaxColorsHardLimit;
			if (!GameModeManager.CurrentHandler.AllowTeams)
			{
				int num2 = PlayerExtensions.colorID(characterSelectionInstance.currentPlayer);
				while (PlayerManager.instance.players.Select((Player p) => PlayerExtensions.colorID(p)).Contains(num) && num != num2)
				{
					num = (num + colorIDDelta + RWFMod.MaxColorsHardLimit) % RWFMod.MaxColorsHardLimit;
				}
			}
			return num;
		}

		private void UpdateText(int selectedColor)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			PlayerSkin playerSkinColors = PlayerSkinBank.GetPlayerSkinColors(selectedColor);
			((TMP_Text)teamText).text = "TEAM: <color=#" + ColorUtility.ToHtmlStringRGB(playerSkinColors.color * 1.5f) + ">" + ExtraPlayerSkins.GetTeamColorName(selectedColor).ToUpper();
		}

		private static void SimulatePress(PlayerAction action)
		{
			((OneAxisInputControl)action).CommitWithValue(1f, (ulong)ExtensionMethods.GetFieldValue((object)action, "pendingTick"), 0f);
		}
	}
}
namespace RoundsWithBots.Patches
{
	[HarmonyPatch(typeof(CharacterSelectionInstance))]
	internal class CharacterSelectionInstancePatch
	{
		public static Dictionary<CharacterSelectionInstance, bool> RequestColorChange = new Dictionary<CharacterSelectionInstance, bool>();

		[HarmonyPatch("StartPicking")]
		[HarmonyBefore(new string[] { "io.olavim.rounds.rwf" })]
		[HarmonyPostfix]
		public static void StartPickingPostfix(CharacterSelectionInstance __instance, Player pickingPlayer)
		{
			if (((Behaviour)((Component)__instance.currentPlayer).GetComponent<PlayerAPI>()).enabled)
			{
				if (RWBMenu.RandomizationFace.Value)
				{
					__instance.currentlySelectedFace = Random.Range(0, 7);
				}
				else
				{
					__instance.currentlySelectedFace = RWBMenu.SelectedFace.Value;
				}
			}
			ExtensionMethods.ExecuteAfterFrames((MonoBehaviour)(object)__instance, 1, (Action)delegate
			{
				((Component)((Component)__instance).transform.GetChild(0).GetChild(1)).gameObject.SetActive(false);
				SetupButton(__instance);
			});
		}

		private static void SetupButton(CharacterSelectionInstance __instance)
		{
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_00e2: Expected O, but got Unknown
			GameObject[] array = (from x in ((Component)((Component)__instance).transform.GetChild(0).GetChild(0)).GetComponentsInChildren<HoverEvent>(true)
				select ((Component)x).gameObject).ToArray();
			UnityAction val2 = default(UnityAction);
			foreach (GameObject val in array)
			{
				if (((Behaviour)((Component)__instance.currentPlayer).GetComponent<PlayerAPI>()).enabled)
				{
					GameObject gameObject = ((Component)val.transform.Find("Tooltip")).gameObject;
					Button orAddComponent = ExtensionMethods.GetOrAddComponent<Button>(gameObject, false);
					Image componentInChildren = gameObject.GetComponentInChildren<Image>(true);
					TextMeshProUGUI componentInChildren2 = gameObject.GetComponentInChildren<TextMeshProUGUI>();
					ControllerImageToggler component = ((Component)componentInChildren).GetComponent<ControllerImageToggler>();
					((UnityEventBase)orAddComponent.onClick).RemoveAllListeners();
					ButtonClickedEvent onClick = orAddComponent.onClick;
					UnityAction obj = val2;
					if (obj == null)
					{
						UnityAction val3 = delegate
						{
							//IL_000a: Unknown result type (might be due to invalid IL or missing references)
							//IL_000f: Unknown result type (might be due to invalid IL or missing references)
							//IL_0014: Unknown result type (might be due to invalid IL or missing references)
							//IL_0028: Unknown result type (might be due to invalid IL or missing references)
							//IL_003c: Unknown result type (might be due to invalid IL or missing references)
							//IL_0041: Unknown result type (might be due to invalid IL or missing references)
							//IL_0057: Unknown result type (might be due to invalid IL or missing references)
							//IL_0058: Unknown result type (might be due to invalid IL or missing references)
							//IL_005d: Unknown result type (might be due to invalid IL or missing references)
							Debug.Log((object)"The bot have be clicked.");
							Vector2 val5 = Vector2.op_Implicit(Input.mousePosition);
							BotMenuUIHandler botMenuUIHandler = BotMenuUIHandler.Show(__instance);
							RectTransform component2 = ((Component)botMenuUIHandler).GetComponent<RectTransform>();
							Vector2 val6 = default(Vector2);
							RectTransformUtility.ScreenPointToLocalPointInRectangle(component2, val5, (Camera)null, ref val6);
							ref float y = ref val6.y;
							float num = y;
							Rect rect = component2.rect;
							y = num - ((Rect)(ref rect)).height / 2f;
							((Component)botMenuUIHandler).transform.position = ((Transform)component2).TransformPoint(Vector2.op_Implicit(val6));
						};
						UnityAction val4 = val3;
						val2 = val3;
						obj = val4;
					}
					((UnityEvent)onClick).AddListener(obj);
					((Selectable)orAddComponent).targetGraphic = (Graphic)(object)componentInChildren2;
					componentInChildren.overrideSprite = component.MKSprite;
					((Component)componentInChildren).transform.localEulerAngles = new Vector3(0f, 180f, 0f);
					((TMP_Text)componentInChildren2).text = "TO EDIT";
					((Selectable)orAddComponent).interactable = true;
				}
				else
				{
					GameObject gameObject2 = ((Component)val.transform.Find("Tooltip")).gameObject;
					Button orAddComponent2 = ExtensionMethods.GetOrAddComponent<Button>(gameObject2, false);
					Image componentInChildren3 = gameObject2.GetComponentInChildren<Image>(true);
					((Component)componentInChildren3).transform.localEulerAngles = new Vector3(0f, 0f, 0f);
					componentInChildren3.overrideSprite = null;
					((Selectable)orAddComponent2).interactable = false;
					((Selectable)orAddComponent2).targetGraphic = null;
				}
				val.GetComponent<SimulatedSelection>().Select();
			}
		}

		[HarmonyPatch("Update")]
		[HarmonyBefore(new string[] { "io.olavim.rounds.rwf" })]
		[HarmonyPrefix]
		public static bool UpdatePrefix(CharacterSelectionInstance __instance)
		{
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance.currentPlayer == (Object)null)
			{
				return false;
			}
			GameObject[] array = (from x in ((Component)((Component)__instance).transform.GetChild(0).GetChild(0)).GetComponentsInChildren<HoverEvent>(true)
				select ((Component)x).gameObject).ToArray();
			if (RequestColorChange.ContainsKey(__instance) && RequestColorChange[__instance])
			{
				GameObject[] array2 = array;
				foreach (GameObject obj in array2)
				{
					((Component)obj.transform.GetChild(2).GetChild(0)).GetComponent<SpriteRenderer>().color = __instance.currentPlayer.GetTeamColors().color;
					((TMP_Text)((Component)obj.transform.GetChild(4).GetChild(2)).GetComponent<TextMeshProUGUI>()).text = (GameModeManager.CurrentHandler.AllowTeams ? "TEAM " : "") + ExtraPlayerSkins.GetTeamColorName(PlayerExtensions.colorID(__instance.currentPlayer)).ToUpper();
				}
				if (RequestColorChange.ContainsKey(__instance))
				{
					RequestColorChange[__instance] = false;
				}
				else
				{
					RequestColorChange.Add(__instance, value: false);
				}
			}
			if (((Behaviour)((Component)__instance.currentPlayer).GetComponent<PlayerAPI>()).enabled)
			{
				ExtensionMethods.SetFieldValue((object)__instance.currentPlayer.data.playerVel, "simulated", (object)false);
				if (__instance.currentPlayer.data.playerActions == null)
				{
					__instance.currentPlayer.data.playerActions = new PlayerActions();
					((PlayerActionSet)__instance.currentPlayer.data.playerActions).Device = InputDevice.Null;
				}
				if (Input.GetKeyDown((KeyCode)114))
				{
					AccessTools.Method(typeof(CharacterSelectionInstance), "ReadyUp", (Type[])null, (Type[])null).Invoke(__instance, null);
					return false;
				}
			}
			return true;
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void StartPostfix(CharacterSelectionInstance __instance)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			GameObject gameObject = ((Component)((Component)__instance).transform.GetChild(0).GetChild(0)).gameObject;
			for (int i = 0; i < gameObject.transform.childCount; i++)
			{
				Button button = ((Component)gameObject.transform.GetChild(i)).GetComponent<Button>();
				((UnityEventBase)button.onClick).RemoveAllListeners();
				((UnityEvent)button.onClick).AddListener((UnityAction)delegate
				{
					if (!((Object)(object)__instance.currentPlayer == (Object)null) && __instance.currentPlayer.data.GetAdditionalData().IsBot)
					{
						Debug.Log((object)"The bot have be clicked.");
						((Component)button).gameObject.GetComponent<ScaleShake>().AddForce();
					}
				});
			}
		}
	}
	[HarmonyPatch(typeof(Map))]
	internal class MapPatch
	{
		[HarmonyPatch("StartMatch")]
		public static void Postfix()
		{
			((MonoBehaviour)RoundsWithBots.Instance).StartCoroutine(SetDamageBoxesColliders());
		}

		public static IEnumerator SetDamageBoxesColliders()
		{
			yield return null;
			List<DamageBox> list = Object.FindObjectsOfType<DamageBox>().ToList();
			PlayerAIPhilipPatch.DamageBoxesColliders.Clear();
			foreach (DamageBox item in list)
			{
				PlayerAIPhilipPatch.DamageBoxesColliders.Add(((Component)item).GetComponent<Collider2D>());
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAIPhilip))]
	internal class PlayerAIPhilipPatch
	{
		private const float maxDistance = 1f;

		public static List<Collider2D> DamageBoxesColliders = new List<Collider2D>();

		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		public static void UpdatePostfix(PlayerAIPhilip __instance)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			GeneralInput val = (GeneralInput)AccessTools.Field(typeof(PlayerAPI), "input").GetValue(((Component)__instance).GetComponentInParent<PlayerAPI>());
			OutOfBoundsHandler obj = Object.FindObjectOfType<OutOfBoundsHandler>();
			Vector3 val2 = (Vector3)AccessTools.Method(typeof(OutOfBoundsHandler), "GetPoint", (Type[])null, (Type[])null).Invoke(obj, new object[1] { ((Component)__instance).transform.position });
			float num = Mathf.Abs(((Component)__instance).transform.position.x - val2.x);
			float num2 = Mathf.Abs(((Component)__instance).transform.position.y - val2.y);
			if ((num <= 1f || num2 <= 1f) && (num >= 1f || num2 >= 1f))
			{
				val.shieldWasPressed = true;
			}
			foreach (Collider2D damageBoxesCollider in DamageBoxesColliders)
			{
				if (!((Object)(object)damageBoxesCollider == (Object)null))
				{
					Bounds bounds = damageBoxesCollider.bounds;
					if (Vector2.Distance(Vector2.op_Implicit(((Bounds)(ref bounds)).ClosestPoint(((Component)__instance).transform.position)), Vector2.op_Implicit(((Component)__instance).transform.position)) <= 1f)
					{
						val.shieldWasPressed = true;
						break;
					}
				}
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch("CanSee")]
		public static IEnumerable<CodeInstruction> CanSeeTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			return ApplyLayerMaskToRaycast(instructions);
		}

		[HarmonyTranspiler]
		[HarmonyPatch("CheckGround")]
		public static IEnumerable<CodeInstruction> CheckGroundTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			return ApplyLayerMaskToRaycast(instructions);
		}

		private static IEnumerable<CodeInstruction> ApplyLayerMaskToRaycast(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo raycastMethod = AccessTools.Method(typeof(Physics2D), "Raycast", new Type[4]
			{
				typeof(Vector2),
				typeof(Vector2),
				typeof(float),
				typeof(int)
			}, (Type[])null);
			int num = LayerMask.NameToLayer("BackgroundObject");
			int layerMask = ~(1 << num);
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Call && instruction.operand is MethodInfo methodInfo && methodInfo.Name == "Raycast")
				{
					yield return new CodeInstruction(OpCodes.Ldc_I4, (object)layerMask);
					yield return new CodeInstruction(OpCodes.Call, (object)raycastMethod);
				}
				else
				{
					yield return instruction;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAssigner))]
	internal class PlayerAssignerPatch
	{
		[HarmonyPatch("CreatePlayer")]
		public static bool Prefix(bool isAI, ref IEnumerator __result)
		{
			if (GameManager.instance.isPlaying && !AIMinionHandler.sandbox)
			{
				__result = EmptyEnumerator();
				return false;
			}
			if (isAI)
			{
				((MonoBehaviour)RoundsWithBots.Instance).StartCoroutine(DelayedAIReplacement());
			}
			return true;
		}

		private static IEnumerator DelayedAIReplacement()
		{
			yield return null;
			Player val = PlayerManager.instance.players.Last();
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogError("Player could not be found.");
				yield break;
			}
			MonoBehaviour val2 = (MonoBehaviour)(((object)((Component)val).GetComponentInChildren<PlayerAI>()) ?? ((object)((Component)val).GetComponentInChildren<PlayerAIZorro>()));
			if ((Object)(object)val2 != (Object)null)
			{
				PlayerAIZorro val3 = (PlayerAIZorro)(object)((val2 is PlayerAIZorro) ? val2 : null);
				if (val3 != null)
				{
					HealthHandler healthHandler = val.data.healthHandler;
					healthHandler.delayedReviveAction = (Action)Delegate.Remove(healthHandler.delayedReviveAction, new Action(val3.Init));
				}
				((Component)val2).gameObject.AddComponent<PlayerAIPhilip>();
				val.data.GetAdditionalData().IsBot = true;
				Object.Destroy((Object)(object)val2);
			}
		}

		private static IEnumerator EmptyEnumerator()
		{
			yield break;
		}
	}
}
namespace RoundsWithBots.Patches.RWF
{
	[HarmonyPatch(typeof(KeybindHints))]
	internal class KeybindHintsPatch
	{
		[HarmonyPatch("CreateLocalHints")]
		public static void Postfix()
		{
			if (PlayerPrefs.GetInt(RWFMod.GetCustomPropertyKey("ShowKeybinds"), 1) != 0)
			{
				KeybindHints.AddHint("to ready up all bots", "[R]", (Vector2?)null);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerSpotlight))]
	internal class RWFAddSpotToPlayerPatch
	{
		[HarmonyPatch("AddSpotToPlayer")]
		public static bool Prefix(Player player)
		{
			return !((Behaviour)((Component)player).GetComponent<PlayerAPI>()).enabled;
		}
	}
}
namespace RoundsWithBots.Menu
{
	internal static class RWBMenu
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__4_0;

			public static UnityAction<float> <>9__4_1;

			public static UnityAction<float> <>9__4_2;

			public static UnityAction<float> <>9__4_3;

			public static UnityAction<float> <>9__4_4;

			public static UnityAction <>9__8_0;

			public static UnityAction<bool> <>9__8_1;

			public static UnityAction<float> <>9__8_2;

			public static UnityAction <>9__10_0;

			public static UnityAction<bool> <>9__11_0;

			public static UnityAction <>9__16_0;

			public static UnityAction<float> <>9__16_1;

			public static UnityAction<float> <>9__16_2;

			public static UnityAction<float> <>9__16_3;

			internal void <CreateCardsPickerMenu>b__4_0()
			{
			}

			internal void <CreateCardsPickerMenu>b__4_1(float value)
			{
				CycleDelay.Value = value;
			}

			internal void <CreateCardsPickerMenu>b__4_2(float value)
			{
				PreCycleDelay.Value = value;
			}

			internal void <CreateCardsPickerMenu>b__4_3(float value)
			{
				GoToCardDelay.Value = value;
			}

			internal void <CreateCardsPickerMenu>b__4_4(float value)
			{
				PickDelay.Value = value;
			}

			internal void <CreateDetailsMenu>b__8_0()
			{
			}

			internal void <CreateDetailsMenu>b__8_1(bool value)
			{
				RandomizationFace.Value = value;
				SelectedFaceObject.SetActive(!value);
			}

			internal void <CreateDetailsMenu>b__8_2(float value)
			{
				SelectedFace.Value = (int)value;
			}

			internal void <RegisterMenu>b__10_0()
			{
			}

			internal void <CreateRWBMenu>b__11_0(bool value)
			{
				DebugMode.Value = value;
			}

			internal void <CreateStalemateMenu>b__16_0()
			{
			}

			internal void <CreateStalemateMenu>b__16_1(float value)
			{
				StalemateTimer.Value = value;
			}

			internal void <CreateStalemateMenu>b__16_2(float value)
			{
				StalemateDamageCooldown.Value = value;
			}

			internal void <CreateStalemateMenu>b__16_3(float value)
			{
				StalemateDamageDuration.Value = value;
			}
		}

		public static ConfigEntry<float> CycleDelay;

		public static ConfigEntry<float> PreCycleDelay;

		public static ConfigEntry<float> GoToCardDelay;

		public static ConfigEntry<float> PickDelay;

		public static GameObject SelectedFaceObject;

		public static ConfigEntry<bool> RandomizationFace;

		public static ConfigEntry<int> SelectedFace;

		public static ConfigEntry<bool> DebugMode;

		public static ConfigEntry<float> StalemateTimer;

		public static ConfigEntry<float> StalemateDamageCooldown;

		public static ConfigEntry<float> StalemateDamageDuration;

		private static void CreateCardsPickerMenu(GameObject mainMenu)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			object obj = <>c.<>9__4_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
				};
				<>c.<>9__4_0 = val;
				obj = (object)val;
			}
			GameObject val2 = MenuHandler.CreateMenu("Cards Picker", (UnityAction)obj, mainMenu, 40, true, true, ((Component)mainMenu.transform.parent).gameObject, true, -1);
			TextMeshProUGUI val3 = default(TextMeshProUGUI);
			MenuHandler.CreateText("<b>Rounds With Bots | Cards Picker", val2, ref val3, 70, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			AddBlank(val2, 50);
			Slider val4 = default(Slider);
			MenuHandler.CreateSlider("Cycle Delay", val2, 30, 0f, 1f, CycleDelay.Value, (UnityAction<float>)delegate(float value)
			{
				CycleDelay.Value = value;
			}, ref val4, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			AddBlank(val2, 20);
			MenuHandler.CreateSlider("Pre-Cycle Delay", val2, 30, 0f, 5f, PreCycleDelay.Value, (UnityAction<float>)delegate(float value)
			{
				PreCycleDelay.Value = value;
			}, ref val4, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			AddBlank(val2, 20);
			MenuHandler.CreateSlider("Go To Card Delay", val2, 30, 0f, 1f, GoToCardDelay.Value, (UnityAction<float>)delegate(float value)
			{
				GoToCardDelay.Value = value;
			}, ref val4, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			AddBlank(val2, 20);
			MenuHandler.CreateSlider("Pick Delay", val2, 30, 0f, 5f, PickDelay.Value, (UnityAction<float>)delegate(float value)
			{
				PickDelay.Value = value;
			}, ref val4, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		}

		private static void CreateDetailsMenu(GameObject mainMenu)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			object obj = <>c.<>9__8_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
				};
				<>c.<>9__8_0 = val;
				obj = (object)val;
			}
			GameObject val2 = MenuHandler.CreateMenu("Bot Details", (UnityAction)obj, mainMenu, 40, true, true, ((Component)mainMenu.transform.parent).gameObject, true, -1);
			TextMeshProUGUI val3 = default(TextMeshProUGUI);
			MenuHandler.CreateText("<b>Rounds With Bots | Bot Details", val2, ref val3, 70, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			AddBlank(val2, 50);
			MenuHandler.CreateToggle(RandomizationFace.Value, "Randomize Bot Faces", val2, (UnityAction<bool>)delegate(bool value)
			{
				RandomizationFace.Value = value;
				SelectedFaceObject.SetActive(!value);
			}, 30, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			AddBlank(val2, 20);
			Slider val4 = default(Slider);
			SelectedFaceObject = MenuHandler.CreateSlider("Selected Bot Face", val2, 30, 0f, 7f, (float)SelectedFace.Value, (UnityAction<float>)delegate(float value)
			{
				SelectedFace.Value = (int)value;
			}, ref val4, true, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			SelectedFaceObject.SetActive(!RandomizationFace.Value);
		}

		public static void RegisterMenu(string modName, ConfigFile config)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			object obj = <>c.<>9__10_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
				};
				<>c.<>9__10_0 = val;
				obj = (object)val;
			}
			Unbound.RegisterMenu(modName, (UnityAction)obj, (Action<GameObject>)CreateRWBMenu, (GameObject)null, false);
			DebugMode = config.Bind<bool>(modName, "DebugMode", false, "Enable or disable debug mode for additional logging and debugging features.");
			RandomizationFace = config.Bind<bool>(modName, "RandomizationFace", true, "Enable or disable randomization of bot faces.");
			SelectedFace = config.Bind<int>(modName, "SelectedFace", 0, "Select a specific bot face when Randomize Bot Faces is disabled.");
			StalemateTimer = config.Bind<float>(modName, "StalemateTimer", 10f, "The time in seconds before a stalemate is declared.");
			StalemateDamageCooldown = config.Bind<float>(modName, "StalemateDamageCooldown", 1f, "The time in seconds before a player can take damage again after a stalemate.");
			StalemateDamageDuration = config.Bind<float>(modName, "StalemateDamageDuration", 10f, "The time in seconds that a player takes damage after a stalemate.");
			CycleDelay = config.Bind<float>(modName, "CycleDelay", 0.3f, "The delay between cycling through cards.");
			PreCycleDelay = config.Bind<float>(modName, "PreCycleDelay", 1f, "The delay before cycling through cards.");
			GoToCardDelay = config.Bind<float>(modName, "GoToCardDelay", 0.2f, "The delay between going to a specific card.");
			PickDelay = config.Bind<float>(modName, "PickDelay", 0.5f, "The delay before picking a card.");
		}

		private static void CreateRWBMenu(GameObject mainMenu)
		{
			TextMeshProUGUI val = default(TextMeshProUGUI);
			MenuHandler.CreateText("<b>Rounds With Bots", mainMenu, ref val, 70, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			AddBlank(mainMenu, 50);
			CreateDetailsMenu(mainMenu);
			AddBlank(mainMenu, 20);
			CreateStalemateMenu(mainMenu);
			AddBlank(mainMenu, 20);
			CreateCardsPickerMenu(mainMenu);
			AddBlank(mainMenu, 20);
			MenuHandler.CreateToggle(DebugMode.Value, "<#c41010>Debug Mode", mainMenu, (UnityAction<bool>)delegate(bool value)
			{
				DebugMode.Value = value;
			}, 30, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		}

		private static void AddBlank(GameObject menu, int size = 30)
		{
			TextMeshProUGUI val = default(TextMeshProUGUI);
			MenuHandler.CreateText(" ", menu, ref val, size, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		}

		private static void CreateStalemateMenu(GameObject mainMenu)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			object obj = <>c.<>9__16_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
				};
				<>c.<>9__16_0 = val;
				obj = (object)val;
			}
			GameObject val2 = MenuHandler.CreateMenu("Stalemate Options", (UnityAction)obj, mainMenu, 40, true, true, ((Component)mainMenu.transform.parent).gameObject, true, -1);
			TextMeshProUGUI val3 = default(TextMeshProUGUI);
			MenuHandler.CreateText("<b>Rounds With Bots | Stalemate Options", val2, ref val3, 70, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			AddBlank(val2, 50);
			Slider val4 = default(Slider);
			MenuHandler.CreateSlider("Stalemate Timer", val2, 30, 0f, 60f, StalemateTimer.Value, (UnityAction<float>)delegate(float value)
			{
				StalemateTimer.Value = value;
			}, ref val4, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			AddBlank(val2, 20);
			MenuHandler.CreateSlider("Stalemate Damage Cooldown", val2, 30, 0f, 60f, StalemateDamageCooldown.Value, (UnityAction<float>)delegate(float value)
			{
				StalemateDamageCooldown.Value = value;
			}, ref val4, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
			AddBlank(val2, 20);
			MenuHandler.CreateSlider("Stalemate Damage Duration", val2, 30, 0f, 60f, StalemateDamageDuration.Value, (UnityAction<float>)delegate(float value)
			{
				StalemateDamageDuration.Value = value;
			}, ref val4, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		}
	}
}
namespace RoundsWithBots.Extensions
{
	[Serializable]
	public class CharacterDataAdditionalData
	{
		public bool IsBot { get; set; }

		public CharacterDataAdditionalData()
		{
			IsBot = false;
		}
	}
	public static class CharacterDataExtension
	{
		public static readonly ConditionalWeakTable<CharacterData, CharacterDataAdditionalData> data = new ConditionalWeakTable<CharacterData, CharacterDataAdditionalData>();

		public static CharacterDataAdditionalData GetAdditionalData(this CharacterData characterData)
		{
			return data.GetOrCreateValue(characterData);
		}

		public static void AddData(this CharacterData characterData, CharacterDataAdditionalData value)
		{
			try
			{
				data.Add(characterData, value);
			}
			catch (Exception)
			{
			}
		}
	}
}
namespace RoundsWithBots.CardPickerAIs
{
	public interface ICardPickerAI
	{
		List<CardInfo> PickCard(List<CardInfo> cards);
	}
	public class RarestCardPicker : ICardPickerAI
	{
		public List<CardInfo> PickCard(List<CardInfo> cards)
		{
			return (from card in cards
				group card by card.rarity into @group
				orderby @group.Key
				select @group).LastOrDefault()?.ToList();
		}
	}
}