Decompiled source of BoplDumBot v1.1.0

BoplDumBot.dll

Decompiled 11 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BoplFixedMath;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[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("BoplDumBot")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Add bots to local Bopl Battle matches - set them up with the game's own UI in character select, then fight them")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("BoplDumBot")]
[assembly: AssemblyTitle("BoplDumBot")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 BoplBotTest
{
	[BepInPlugin("up_iz.bopldumbot", "BoplDumBot", "1.1.0")]
	[BepInProcess("BoplBattle.exe")]
	public class BoplBotTestPlugin : BaseUnityPlugin
	{
		public const string GUID = "up_iz.bopldumbot";

		public const string NAME = "BoplDumBot";

		public const string VERSION = "1.1.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<int> Difficulty;

		internal static ConfigEntry<bool> MirrorLoadout;

		internal static ConfigEntry<string> Ability1;

		internal static ConfigEntry<string> Ability2;

		internal static ConfigEntry<string> Ability3;

		private void Awake()
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Expected O, but got Unknown
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Expected O, but got Unknown
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Expected O, but got Unknown
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Expected O, but got Unknown
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Expected O, but got Unknown
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Expected O, but got Unknown
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Expected O, but got Unknown
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Expected O, but got Unknown
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Application.targetFrameRate = 60;
			Difficulty = ((BaseUnityPlugin)this).Config.Bind<int>("Bot", "Difficulty", 1, "this is experimental super super dum still lol");
			MirrorLoadout = ((BaseUnityPlugin)this).Config.Bind<bool>("Bot", "MirrorLoadout", true, "true = the bot gets the same abilities you picked in character select");
			Ability1 = ((BaseUnityPlugin)this).Config.Bind<string>("Bot", "Ability1", "", "Force bot ability slot 1 by name (full list printed to LogOutput.log). empty = automatic");
			Ability2 = ((BaseUnityPlugin)this).Config.Bind<string>("Bot", "Ability2", "", "Force bot ability slot 2 by name. empty = automatic");
			Ability3 = ((BaseUnityPlugin)this).Config.Bind<string>("Bot", "Ability3", "", "Force bot ability slot 3 by name. empty = automatic");
			Harmony val = new Harmony("up_iz.bopldumbot");
			val.Patch((MethodBase)AccessTools.Method(typeof(CharacterSelectHandler), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "CharSelectAwake_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.Method(typeof(CharacterSelectHandler), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "CharSelectStart_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.Method(typeof(CharacterSelectHandler), "TryStartGame_inner", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "TryStartGame_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.Method(typeof(InputUpdater), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "InputUpdate_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.Method(typeof(CharacterSelectBox), "LateUpdate", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "BotBoxKeyboard_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.Method(typeof(SelectAbility), "Update", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "BotSubKeyboard_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.Method(typeof(TeamSelector), "Update", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "BotTeamKeyboard_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.Method(typeof(SelectColor), "Update", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "BotColorKeyboard_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.Method(typeof(ReadyButton), "Update", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "BotReadyKeyboard_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.Method(typeof(CharacterSelectBox), "OnEnterReady", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "BotReadied_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.Method(typeof(CharacterSelectBox), "OnEnterSelect", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "BotUnreadied_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Log.LogInfo((object)"[bot] BoplDumBot v1.1.0 loaded - ADD BOT button appears in character select");
		}
	}
	public static class Patches
	{
		private static bool _brainCreated;

		public static void CharSelectAwake_Postfix(CharacterSelectHandler __instance)
		{
			BotRegistry.StripBots();
			BotButton.Build(__instance);
			BotRegistry.DumpAbilityNames();
		}

		public static void CharSelectStart_Postfix(CharacterSelectHandler __instance)
		{
			BotBox.Sync(__instance);
		}

		public static void TryStartGame_Postfix(CharacterSelectHandler __instance)
		{
			if (!BotBox.TryConvertBuiltBot(__instance) && BotBox.Specs.Count > 0)
			{
				BoplBotTestPlugin.Log.LogInfo((object)"[bot] no readied bot boxes - bots skipped this match (press their READY buttons)");
			}
		}

		public static void InputUpdate_Postfix()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (_brainCreated)
			{
				return;
			}
			_brainCreated = true;
			try
			{
				GameObject val = new GameObject("BoplBotTest_Host");
				Object.DontDestroyOnLoad((Object)val);
				((Object)val).hideFlags = (HideFlags)1;
				val.AddComponent<BotHost>();
				BoplBotTestPlugin.Log.LogInfo((object)"[bot] brain host online");
			}
			catch (Exception ex)
			{
				BoplBotTestPlugin.Log.LogInfo((object)("[bot] brain host failed: " + ex.Message));
			}
		}

		public static bool BotBoxKeyboard_Prefix(CharacterSelectBox __instance)
		{
			return !BotBox.Boxes.Contains(__instance);
		}

		public static bool BotSubKeyboard_Prefix(SelectAbility __instance)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				return !BotBox.Boxes.Contains(__instance.csb);
			}
			return true;
		}

		public static bool BotTeamKeyboard_Prefix(TeamSelector __instance)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				return !BotBox.Boxes.Contains(__instance.csb);
			}
			return true;
		}

		public static bool BotColorKeyboard_Prefix(SelectColor __instance)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				return !BotBox.Boxes.Contains(__instance.csb);
			}
			return true;
		}

		public static bool BotReadyKeyboard_Prefix(ReadyButton __instance)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				return !BotBox.Boxes.Contains(__instance.charSelectBox);
			}
			return true;
		}

		public static void BotReadied_Postfix(CharacterSelectBox __instance)
		{
			BotBox.BotSpec botSpec = BotBox.SpecOf(__instance);
			if (botSpec != null)
			{
				botSpec.wasReady = true;
				BotBox.Snapshot(__instance, botSpec);
				BoplBotTestPlugin.Log.LogInfo((object)"[bot] bot readied via the game's own READY button");
			}
		}

		public static void BotUnreadied_Postfix(CharacterSelectBox __instance)
		{
			BotBox.BotSpec botSpec = BotBox.SpecOf(__instance);
			if (botSpec != null)
			{
				botSpec.wasReady = false;
			}
		}
	}
	public static class BotButton
	{
		private static bool _warningClosed;

		public static void Build(CharacterSelectHandler h)
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Canvas val = (((Object)(object)h != (Object)null && (Object)(object)h.startText != (Object)null) ? ((Graphic)h.startText).canvas : null);
				if ((Object)(object)val == (Object)null)
				{
					BoplBotTestPlugin.Log.LogWarning((object)"[bot] no canvas found - buttons skipped");
					return;
				}
				TMP_FontAsset val2 = null;
				try
				{
					val2 = ((TMP_Text)h.startText).font;
				}
				catch
				{
				}
				if ((Object)(object)val2 == (Object)null)
				{
					try
					{
						val2 = LocalizedText.localizationTable.GetFont(Settings.Get().Language, false);
					}
					catch
					{
					}
				}
				MakeBtn(((Component)val).transform, h, "AddBot", 108f, "+ ADD BOT", new Color(0.12f, 0.35f, 0.75f, 0.92f), delegate
				{
					BotBox.AddBot(h, 1);
				});
				MakeBtn(((Component)val).transform, h, "DiceBot", 64f, "+ DICE BOT (random every game)", new Color(0.12f, 0.35f, 0.75f, 0.92f), delegate
				{
					BotBox.AddBot(h, 2);
				});
				MakeBtn(((Component)val).transform, h, "RemoveBot", 20f, "- REMOVE BOT", new Color(0.55f, 0.16f, 0.14f, 0.92f), delegate
				{
					BotBox.RemoveLast(h);
				});
				MakeWarningBubble(((Component)val).transform, h);
			}
			catch (Exception arg)
			{
				BoplBotTestPlugin.Log.LogWarning((object)$"[bot] buttons failed: {arg}");
			}
		}

		private static void MakeWarningBubble(Transform canvas, CharacterSelectHandler h)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03be: Unknown result type (might be due to invalid IL or missing references)
			//IL_042a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Expected O, but got Unknown
			//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0511: Unknown result type (might be due to invalid IL or missing references)
			//IL_0544: Unknown result type (might be due to invalid IL or missing references)
			//IL_0549: Unknown result type (might be due to invalid IL or missing references)
			//IL_055b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0562: Unknown result type (might be due to invalid IL or missing references)
			//IL_056d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0578: Unknown result type (might be due to invalid IL or missing references)
			//IL_057d: Unknown result type (might be due to invalid IL or missing references)
			//IL_057e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0585: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0619: Unknown result type (might be due to invalid IL or missing references)
			//IL_0623: Expected O, but got Unknown
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c6: Unknown result type (might be due to invalid IL or missing references)
			if (_warningClosed)
			{
				return;
			}
			GameObject bubble = new GameObject("BoplDumBot_Warning", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			bubble.transform.SetParent(canvas, false);
			RectTransform component = bubble.GetComponent<RectTransform>();
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(1f, 1f);
			component.anchorMax = val;
			component.anchorMin = val;
			component.pivot = new Vector2(0.5f, 0.5f);
			component.anchoredPosition = new Vector2(-250f, -78f);
			component.sizeDelta = new Vector2(460f, 118f);
			((Graphic)bubble.GetComponent<Image>()).color = new Color(1f, 0.62f, 0.16f, 0.95f);
			GameObject val2 = new GameObject("Inner", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val2.transform.SetParent(bubble.transform, false);
			RectTransform component2 = val2.GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = new Vector2(4f, 4f);
			component2.offsetMax = new Vector2(-4f, -4f);
			((Graphic)val2.GetComponent<Image>()).color = new Color(0.07f, 0.1f, 0.2f, 0.93f);
			GameObject val3 = new GameObject("TailBorder", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val3.transform.SetParent(bubble.transform, false);
			RectTransform component3 = val3.GetComponent<RectTransform>();
			((Vector2)(ref val))..ctor(0.5f, 0f);
			component3.anchorMax = val;
			component3.anchorMin = val;
			component3.pivot = new Vector2(0.5f, 0.5f);
			component3.anchoredPosition = new Vector2(0f, -16f);
			component3.sizeDelta = new Vector2(30f, 30f);
			((Transform)component3).localRotation = Quaternion.Euler(0f, 0f, 45f);
			((Graphic)val3.GetComponent<Image>()).color = new Color(1f, 0.62f, 0.16f, 0.95f);
			GameObject val4 = new GameObject("TailInner", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val4.transform.SetParent(bubble.transform, false);
			RectTransform component4 = val4.GetComponent<RectTransform>();
			((Vector2)(ref val))..ctor(0.5f, 0f);
			component4.anchorMax = val;
			component4.anchorMin = val;
			component4.pivot = new Vector2(0.5f, 0.5f);
			component4.anchoredPosition = new Vector2(0f, -11f);
			component4.sizeDelta = new Vector2(22f, 22f);
			((Transform)component4).localRotation = Quaternion.Euler(0f, 0f, 45f);
			((Graphic)val4.GetComponent<Image>()).color = new Color(0.07f, 0.1f, 0.2f, 0.93f);
			GameObject val5 = new GameObject("Text", new Type[1] { typeof(RectTransform) });
			val5.transform.SetParent(val2.transform, false);
			RectTransform component5 = val5.GetComponent<RectTransform>();
			component5.anchorMin = Vector2.zero;
			component5.anchorMax = Vector2.one;
			component5.offsetMin = new Vector2(10f, 6f);
			component5.offsetMax = new Vector2(-10f, -6f);
			TextMeshProUGUI val6 = val5.AddComponent<TextMeshProUGUI>();
			try
			{
				((TMP_Text)val6).font = ((TMP_Text)h.startText).font;
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)((TMP_Text)val6).font == (Object)null)
				{
					((TMP_Text)val6).font = LocalizedText.localizationTable.GetFont(Settings.Get().Language, false);
				}
			}
			catch
			{
			}
			((TMP_Text)val6).fontSize = 23f;
			((TMP_Text)val6).alignment = (TextAlignmentOptions)514;
			((Graphic)val6).color = Color.white;
			((TMP_Text)val6).text = "this is still experimental —\nplease don't expect this to work perfect.\nit's in the name.";
			GameObject val7 = new GameObject("CloseX", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val7.transform.SetParent(bubble.transform, false);
			RectTransform component6 = val7.GetComponent<RectTransform>();
			((Vector2)(ref val))..ctor(1f, 1f);
			component6.anchorMax = val;
			component6.anchorMin = val;
			component6.pivot = new Vector2(0.5f, 0.5f);
			component6.anchoredPosition = new Vector2(-26f, -26f);
			component6.sizeDelta = new Vector2(38f, 38f);
			Image component7 = val7.GetComponent<Image>();
			((Graphic)component7).color = new Color(0.55f, 0.16f, 0.14f, 0.95f);
			Button component8 = val7.GetComponent<Button>();
			((Selectable)component8).targetGraphic = (Graphic)(object)component7;
			GameObject val8 = new GameObject("X", new Type[1] { typeof(RectTransform) });
			val8.transform.SetParent(val7.transform, false);
			RectTransform component9 = val8.GetComponent<RectTransform>();
			component9.anchorMin = Vector2.zero;
			component9.anchorMax = Vector2.one;
			val = (component9.offsetMin = (component9.offsetMax = Vector2.zero));
			TextMeshProUGUI val10 = val8.AddComponent<TextMeshProUGUI>();
			try
			{
				((TMP_Text)val10).font = ((TMP_Text)h.startText).font;
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)((TMP_Text)val10).font == (Object)null)
				{
					((TMP_Text)val10).font = LocalizedText.localizationTable.GetFont(Settings.Get().Language, false);
				}
			}
			catch
			{
			}
			((TMP_Text)val10).fontSize = 22f;
			((TMP_Text)val10).alignment = (TextAlignmentOptions)514;
			((Graphic)val10).color = Color.white;
			((TMP_Text)val10).text = "X";
			((UnityEvent)component8.onClick).AddListener((UnityAction)delegate
			{
				_warningClosed = true;
				try
				{
					AudioManager obj5 = AudioManager.Get();
					if (obj5 != null)
					{
						obj5.Play("decline");
					}
				}
				catch
				{
				}
				Object.Destroy((Object)(object)bubble);
			});
		}

		private static TextMeshProUGUI MakeBtn(Transform canvas, CharacterSelectHandler h, string name, float y, string label, Color color, Action onClick)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Expected O, but got Unknown
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("BoplBotTest_" + name, new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent(canvas, false);
			RectTransform component = val.GetComponent<RectTransform>();
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(1f, 0f);
			component.anchorMax = val2;
			component.anchorMin = val2;
			component.pivot = new Vector2(0.5f, 0.5f);
			component.anchoredPosition = new Vector2(-200f, y);
			component.sizeDelta = new Vector2(340f, 40f);
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = color;
			Button component3 = val.GetComponent<Button>();
			((Selectable)component3).targetGraphic = (Graphic)(object)component2;
			GameObject val3 = new GameObject("Label", new Type[1] { typeof(RectTransform) });
			val3.transform.SetParent(val.transform, false);
			RectTransform component4 = val3.GetComponent<RectTransform>();
			component4.anchorMin = Vector2.zero;
			component4.anchorMax = Vector2.one;
			val2 = (component4.offsetMin = (component4.offsetMax = Vector2.zero));
			TextMeshProUGUI val5 = val3.AddComponent<TextMeshProUGUI>();
			try
			{
				((TMP_Text)val5).font = ((TMP_Text)h.startText).font;
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)((TMP_Text)val5).font == (Object)null)
				{
					((TMP_Text)val5).font = LocalizedText.localizationTable.GetFont(Settings.Get().Language, false);
				}
			}
			catch
			{
			}
			((TMP_Text)val5).fontSize = 18f;
			((TMP_Text)val5).alignment = (TextAlignmentOptions)514;
			((Graphic)val5).color = Color.white;
			((TMP_Text)val5).text = label;
			((UnityEvent)component3.onClick).AddListener((UnityAction)delegate
			{
				try
				{
					onClick();
				}
				catch (Exception ex)
				{
					BoplBotTestPlugin.Log.LogWarning((object)("[bot] button: " + ex.Message));
				}
			});
			return val5;
		}
	}
	public static class BotBox
	{
		internal class BotSpec
		{
			internal int mode = 1;

			internal bool wasReady;

			internal int a0 = -1;

			internal int a1 = -1;

			internal int a2 = -1;

			internal CharacterSelectBox box;
		}

		internal static readonly List<BotSpec> Specs = new List<BotSpec>();

		internal static readonly List<CharacterSelectBox> Boxes = new List<CharacterSelectBox>();

		internal static CharacterSelectHandler Handler;

		internal static BotSpec SpecOf(CharacterSelectBox box)
		{
			if ((Object)(object)box == (Object)null)
			{
				return null;
			}
			foreach (BotSpec spec in Specs)
			{
				if ((Object)(object)spec.box == (Object)(object)box)
				{
					return spec;
				}
			}
			return null;
		}

		internal static void Snapshot(CharacterSelectBox box, BotSpec spec)
		{
			try
			{
				if (!((Object)(object)box == (Object)null) && spec != null)
				{
					spec.a0 = box.playerInit.ability0;
					spec.a1 = box.playerInit.ability1;
					spec.a2 = box.playerInit.ability2;
				}
			}
			catch
			{
			}
		}

		private static string Describe(BotSpec spec)
		{
			try
			{
				if (spec == null)
				{
					return "?";
				}
				NamedSpriteList all = SteamManager.instance.abilityIcons;
				return N(spec.a0) + ", " + N(spec.a1) + ", " + N(spec.a2);
				string N(int i)
				{
					//IL_0029: Unknown result type (might be due to invalid IL or missing references)
					if (i < 0 || i >= all.sprites.Count)
					{
						return "?";
					}
					return all.sprites[i].name;
				}
			}
			catch
			{
				return "?";
			}
		}

		public static int FindDiceIndex()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				NamedSpriteList abilityIcons = SteamManager.instance.abilityIcons;
				for (int i = 0; i < abilityIcons.sprites.Count; i++)
				{
					GameObject associatedGameObject = abilityIcons.sprites[i].associatedGameObject;
					if ((Object)(object)associatedGameObject != (Object)null && (Object)(object)associatedGameObject.GetComponent<RandomAbility>() != (Object)null)
					{
						return i;
					}
				}
			}
			catch
			{
			}
			return -1;
		}

		public static void AddBot(CharacterSelectHandler h, int mode)
		{
			try
			{
				BotSpec botSpec = new BotSpec
				{
					mode = mode
				};
				if (mode == 2)
				{
					int num = FindDiceIndex();
					if (num >= 0)
					{
						botSpec.a0 = (botSpec.a1 = (botSpec.a2 = num));
					}
					else
					{
						BoplBotTestPlugin.Log.LogWarning((object)"[bot] couldn't find the game's dice ability");
					}
					botSpec.wasReady = true;
				}
				CharacterSelectBox val = JoinOne(h, botSpec);
				if ((Object)(object)val == (Object)null)
				{
					BoplBotTestPlugin.Log.LogWarning((object)"[bot] no free character box - bot not added");
					return;
				}
				botSpec.box = val;
				Specs.Add(botSpec);
				Boxes.Add(val);
				try
				{
					AudioManager obj = AudioManager.Get();
					if (obj != null)
					{
						obj.Play("accept");
					}
				}
				catch
				{
				}
				BoplBotTestPlugin.Log.LogInfo((object)((mode == 2) ? $"[bot] DICE bot added on box {val.RectangleIndex} - new random abilities every round ({Specs.Count} bot(s) total)" : $"[bot] bot added on box {val.RectangleIndex} - pick its abilities with the game's UI + press its READY button ({Specs.Count} bot(s) total)"));
			}
			catch (Exception arg)
			{
				BoplBotTestPlugin.Log.LogWarning((object)$"[bot] add failed: {arg}");
			}
		}

		public static void RemoveLast(CharacterSelectHandler h)
		{
			try
			{
				if (Specs.Count == 0)
				{
					BoplBotTestPlugin.Log.LogInfo((object)"[bot] no bots to remove");
					return;
				}
				BotSpec botSpec = Specs[Specs.Count - 1];
				if ((Object)(object)botSpec.box != (Object)null)
				{
					TeardownBox(botSpec.box);
				}
				Specs.RemoveAt(Specs.Count - 1);
				BoplBotTestPlugin.Log.LogInfo((object)$"[bot] bot removed ({Specs.Count} bot(s) left)");
			}
			catch (Exception ex)
			{
				BoplBotTestPlugin.Log.LogWarning((object)("[bot] remove failed: " + ex.Message));
			}
		}

		public static void Sync(CharacterSelectHandler h)
		{
			try
			{
				Handler = h;
				List<BotSpec> list = new List<BotSpec>();
				Boxes.Clear();
				foreach (BotSpec spec in Specs)
				{
					spec.box = null;
					CharacterSelectBox val = JoinOne(h, spec);
					if ((Object)(object)val == (Object)null)
					{
						BoplBotTestPlugin.Log.LogWarning((object)"[bot] not enough free boxes - dropping a bot");
						continue;
					}
					spec.box = val;
					Boxes.Add(val);
					list.Add(spec);
				}
				Specs.Clear();
				Specs.AddRange(list);
				if (Specs.Count > 0)
				{
					BoplBotTestPlugin.Log.LogInfo((object)$"[bot] re-claimed {Boxes.Count} bot box(es) for this scene");
				}
			}
			catch (Exception arg)
			{
				BoplBotTestPlugin.Log.LogWarning((object)$"[bot] box sync failed: {arg}");
			}
		}

		private static CharacterSelectBox JoinOne(CharacterSelectHandler h, BotSpec spec)
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			CharacterSelectBox val = null;
			CharacterSelectBox[] characterSelectBoxes = h.characterSelectBoxes;
			foreach (CharacterSelectBox val2 in characterSelectBoxes)
			{
				if ((Object)(object)val2 != (Object)null && (int)val2.menuState == 0)
				{
					val = val2;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			int num = FreeTeam(h, val);
			Material color = FreeMaterial(h, val);
			Player val3 = new Player(99, num);
			val3.UsesKeyboardAndMouse = false;
			val3.Color = color;
			val3.Abilities = BuildTemplateAbilities(h, val, spec);
			CharacterSelectBox.occupiedRectangles[val.RectangleIndex] = true;
			val.currentGamePad = null;
			val.UseskeyboardMouse = true;
			try
			{
				if ((Object)(object)val.rebindImageControllerImage != (Object)null && (Object)(object)val.keyboardMouseSprite != (Object)null)
				{
					val.rebindImageControllerImage.sprite = val.keyboardMouseSprite;
				}
			}
			catch
			{
			}
			Traverse val4 = new Traverse((object)val);
			AnimateInOutUI[] value = val4.Field<AnimateInOutUI[]>("animateSelectables").Value;
			if (value != null)
			{
				AnimateInOutUI[] array = value;
				foreach (AnimateInOutUI val5 in array)
				{
					if ((Object)(object)val5 != (Object)null)
					{
						val5.AnimateIn();
					}
				}
			}
			AnimateInOutUI value2 = val4.Field<AnimateInOutUI>("animateSelect").Value;
			if ((Object)(object)value2 != (Object)null)
			{
				value2.AnimateIn();
			}
			AnimateInOutUI value3 = val4.Field<AnimateInOutUI>("animateJoin").Value;
			if ((Object)(object)value3 != (Object)null)
			{
				value3.AnimateOut();
			}
			val.menuState = (CharSelectMenu)1;
			val.SetSelected(1);
			val.UpdatePlayerInit();
			for (int j = 0; j < val.selectables.Count; j++)
			{
				val.selectables[j].SetToPlayerChoices(val3, j - 2);
			}
			ApplySpecToBox(val, spec);
			Snapshot(val, spec);
			if (spec.wasReady)
			{
				val.OnEnterReady();
				BoplBotTestPlugin.Log.LogInfo((object)$"[bot] box {val.RectangleIndex} re-readied. loadout: {Describe(spec)}");
			}
			return val;
		}

		private static void ApplySpecToBox(CharacterSelectBox box, BotSpec spec)
		{
			if (spec == null || (spec.a0 < 0 && spec.a1 < 0 && spec.a2 < 0))
			{
				return;
			}
			try
			{
				int num = 3;
				try
				{
					num = Settings.Get().NumberOfAbilities;
				}
				catch
				{
				}
				int[] array = new int[3] { spec.a0, spec.a1, spec.a2 };
				for (int i = 0; i < 3; i++)
				{
					if (array[i] < 0)
					{
						continue;
					}
					int num2 = ((num != 3) ? (2 + i) : (i switch
					{
						1 => 4, 
						0 => 2, 
						_ => 3, 
					}));
					if (num2 < box.selectables.Count)
					{
						SelectableMonoBehaviour obj2 = box.selectables[num2];
						SelectAbility val = (SelectAbility)(object)((obj2 is SelectAbility) ? obj2 : null);
						if (val != null)
						{
							((SelectableMonoBehaviour)val).Select(array[i]);
						}
					}
				}
				box.UpdatePlayerInit();
			}
			catch (Exception ex)
			{
				BoplBotTestPlugin.Log.LogWarning((object)("[bot] apply failed: " + ex.Message));
			}
		}

		private static void TeardownBox(CharacterSelectBox box)
		{
			if ((Object)(object)box == (Object)null)
			{
				return;
			}
			try
			{
				box.UseskeyboardMouse = false;
				box.OnEnterSelect();
				box.OnEnterJoin();
			}
			catch
			{
			}
		}

		private static int FreeTeam(CharacterSelectHandler h, CharacterSelectBox botBox)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Invalid comparison between Unknown and I4
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Invalid comparison between Unknown and I4
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			bool[] array = new bool[4];
			CharacterSelectBox[] characterSelectBoxes = h.characterSelectBoxes;
			foreach (CharacterSelectBox val in characterSelectBoxes)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)botBox)
				{
					continue;
				}
				if ((int)val.menuState == 1 || (int)val.menuState == 2 || (int)val.menuState == 3)
				{
					int team = val.playerInit.team;
					if (team >= 0 && team < 4)
					{
						array[team] = true;
					}
				}
				else if ((int)val.menuState == 0)
				{
					TeamSelector val2 = val.selectables.OfType<TeamSelector>().FirstOrDefault();
					if ((Object)(object)val2 != (Object)null && val2.selectedIndex >= 0 && val2.selectedIndex < 4)
					{
						array[val2.selectedIndex] = true;
					}
				}
			}
			int num = Array.IndexOf(array, value: false);
			if (num < 0)
			{
				for (int j = 0; j < 4; j++)
				{
					if (!array[j])
					{
						num = j;
						break;
					}
				}
				if (num < 0)
				{
					num = 0;
				}
				for (int k = 0; k < 4; k++)
				{
					if (array[k])
					{
						num = (k + 1) % 4;
						break;
					}
				}
			}
			return num;
		}

		private static Material FreeMaterial(CharacterSelectHandler h, CharacterSelectBox botBox)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Invalid comparison between Unknown and I4
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Invalid comparison between Unknown and I4
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Invalid comparison between Unknown and I4
			try
			{
				SelectColor val = botBox.selectables.OfType<SelectColor>().FirstOrDefault();
				PlayerColors val2 = (((Object)(object)val != (Object)null) ? val.playerColors : null);
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = (PlayerColors)AccessTools.Field(typeof(CharacterSelectHandler), "playerColors").GetValue(h);
				}
				if ((Object)(object)val2 == (Object)null)
				{
					return null;
				}
				bool[] array = new bool[val2.playerColors.Length];
				CharacterSelectBox[] characterSelectBoxes = h.characterSelectBoxes;
				foreach (CharacterSelectBox val3 in characterSelectBoxes)
				{
					if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3 == (Object)(object)botBox) && ((int)val3.menuState == 1 || (int)val3.menuState == 2 || (int)val3.menuState == 3))
					{
						int color = val3.playerInit.color;
						if (color >= 0 && color < array.Length)
						{
							array[color] = true;
						}
					}
				}
				for (int j = 0; j < val2.playerColors.Length; j++)
				{
					if (!array[j])
					{
						return val2.playerColors[j].playerMaterial;
					}
				}
				return val2.playerColors[0].playerMaterial;
			}
			catch
			{
				return null;
			}
		}

		private static List<GameObject> BuildTemplateAbilities(CharacterSelectHandler h, CharacterSelectBox botBox, BotSpec spec)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Invalid comparison between Unknown and I4
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Invalid comparison between Unknown and I4
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Invalid comparison between Unknown and I4
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			List<GameObject> list = new List<GameObject>();
			NamedSpriteList abilityIcons = SteamManager.instance.abilityIcons;
			if (spec != null && (spec.a0 >= 0 || spec.a1 >= 0 || spec.a2 >= 0))
			{
				int[] array = new int[3] { spec.a0, spec.a1, spec.a2 };
				foreach (int num in array)
				{
					if (num >= 0 && num < abilityIcons.sprites.Count)
					{
						list.Add(abilityIcons.sprites[num].associatedGameObject);
					}
				}
				if (list.Count > 0)
				{
					while (list.Count < 3)
					{
						list.Add(list[list.Count - 1]);
					}
					return list;
				}
			}
			string[] array2 = new string[3]
			{
				BoplBotTestPlugin.Ability1.Value,
				BoplBotTestPlugin.Ability2.Value,
				BoplBotTestPlugin.Ability3.Value
			};
			if (array2.Any((string s) => !string.IsNullOrWhiteSpace(s)))
			{
				string[] array3 = array2;
				foreach (string text in array3)
				{
					if (!string.IsNullOrWhiteSpace(text))
					{
						int num2 = abilityIcons.IndexOf(text.Trim());
						if (num2 < 0)
						{
							BoplBotTestPlugin.Log.LogWarning((object)("[bot] ability '" + text + "' doesn't exist (see the ability list in the log)"));
						}
						else
						{
							list.Add(abilityIcons.sprites[num2].associatedGameObject);
						}
					}
				}
				if (list.Count > 0)
				{
					while (list.Count < 3)
					{
						list.Add(list[list.Count - 1]);
					}
					return list;
				}
				BoplBotTestPlugin.Log.LogWarning((object)"[bot] no valid config abilities - falling back");
			}
			if (BoplBotTestPlugin.MirrorLoadout.Value)
			{
				CharacterSelectBox val = null;
				CharacterSelectBox[] characterSelectBoxes = h.characterSelectBoxes;
				foreach (CharacterSelectBox val2 in characterSelectBoxes)
				{
					if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)botBox && ((int)val2.menuState == 1 || (int)val2.menuState == 2 || (int)val2.menuState == 3))
					{
						val = val2;
						break;
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					PlayerInit playerInit = val.playerInit;
					if (playerInit.ability0 >= 0 && playerInit.ability0 < abilityIcons.sprites.Count)
					{
						list.Add(abilityIcons.sprites[playerInit.ability0].associatedGameObject);
					}
					if (playerInit.ability1 >= 0 && playerInit.ability1 < abilityIcons.sprites.Count)
					{
						list.Add(abilityIcons.sprites[playerInit.ability1].associatedGameObject);
					}
					if (playerInit.ability2 >= 0 && playerInit.ability2 < abilityIcons.sprites.Count)
					{
						list.Add(abilityIcons.sprites[playerInit.ability2].associatedGameObject);
					}
				}
				if (list.Count > 0)
				{
					while (list.Count < 3)
					{
						list.Add(list[list.Count - 1]);
					}
					return list;
				}
			}
			List<NamedSprite> list2 = abilityIcons.sprites.Where((NamedSprite s) => (Object)(object)s.associatedGameObject != (Object)null).ToList();
			while (list.Count < 3 && list2.Count > 0)
			{
				int index = Random.Range(0, list2.Count);
				list.Add(list2[index].associatedGameObject);
				list2.RemoveAt(index);
			}
			while (list.Count < 3 && list.Count > 0)
			{
				list.Add(list[list.Count - 1]);
			}
			return list;
		}

		public static bool TryConvertBuiltBot(CharacterSelectHandler h)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			int num = 0;
			int num2 = 0;
			CharacterSelectBox[] characterSelectBoxes = h.characterSelectBoxes;
			foreach (CharacterSelectBox val in characterSelectBoxes)
			{
				if ((Object)(object)val == (Object)null || (int)val.menuState != 2)
				{
					continue;
				}
				num2++;
				if (!Boxes.Contains(val))
				{
					continue;
				}
				foreach (Player item in PlayerHandler.Get().PlayerList())
				{
					if (item != null && item.Id == num2)
					{
						item.IsLocalPlayer = false;
						item.UsesKeyboardAndMouse = false;
						item.inputDevice = null;
						num++;
						BoplBotTestPlugin.Log.LogInfo((object)($"[bot] box player (id {num2}) converted: team {item.Team}, abilities " + "[" + string.Join(", ", item.Abilities.Select((GameObject a) => ((Object)a).name)) + "] (" + NameForDifficulty() + ")"));
						break;
					}
				}
			}
			if (num > 0)
			{
				BoplBotTestPlugin.Log.LogInfo((object)$"[bot] {num} bot(s) entering the match - each gets its own brain");
			}
			return num > 0;
		}

		private static string NameForDifficulty()
		{
			return BoplBotTestPlugin.Difficulty.Value switch
			{
				0 => "training dummy", 
				2 => "tryhard", 
				_ => "fighter", 
			};
		}
	}
	public static class BotRegistry
	{
		private static bool _namesDumped;

		public static void StripBots()
		{
			try
			{
				List<Player> list = PlayerHandler.Get().PlayerList();
				int num = 0;
				for (int num2 = list.Count - 1; num2 >= 0; num2--)
				{
					if (list[num2] != null && !list[num2].IsLocalPlayer)
					{
						list.RemoveAt(num2);
						num++;
					}
				}
				if (num > 0)
				{
					BoplBotTestPlugin.Log.LogInfo((object)$"[bot] cleared {num} bot(s) from the lobby");
				}
			}
			catch
			{
			}
		}

		public static void DumpAbilityNames()
		{
			if (_namesDumped)
			{
				return;
			}
			_namesDumped = true;
			try
			{
				NamedSpriteList abilityIcons = SteamManager.instance.abilityIcons;
				BoplBotTestPlugin.Log.LogInfo((object)("[bot] all abilities (config names): " + string.Join(", ", abilityIcons.sprites.Select((NamedSprite s) => s.name))));
			}
			catch (Exception ex)
			{
				BoplBotTestPlugin.Log.LogWarning((object)("[bot] ability list dump failed: " + ex.Message));
			}
		}

		public static void AddBot(CharacterSelectHandler h)
		{
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Expected O, but got Unknown
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Expected O, but got Unknown
			try
			{
				List<Player> list = PlayerHandler.Get().PlayerList();
				if (list.Any((Player p) => p != null && !p.IsLocalPlayer))
				{
					BoplBotTestPlugin.Log.LogInfo((object)"[bot] already in the lobby - skipping");
					return;
				}
				List<Player> list2 = list.Where((Player p) => p != null && p.IsLocalPlayer).ToList();
				if (list2.Count == 0)
				{
					return;
				}
				if (list2.Count >= 4)
				{
					BoplBotTestPlugin.Log.LogWarning((object)"[bot] no free player slot (4 humans) - skipping");
					return;
				}
				int num = list2.Count + 1;
				bool[] array = new bool[4];
				foreach (Player item in list2)
				{
					if (item.Team >= 0 && item.Team < 4)
					{
						array[item.Team] = true;
					}
				}
				int num2 = Array.IndexOf(array, value: false);
				if (num2 < 0)
				{
					num2 = 0;
				}
				Material val = null;
				try
				{
					PlayerColors val2 = (PlayerColors)AccessTools.Field(typeof(CharacterSelectHandler), "playerColors").GetValue(h);
					for (int num3 = 0; num3 < val2.playerColors.Length; num3++)
					{
						Material m = val2.playerColors[num3].playerMaterial;
						if (!((Object)(object)m == (Object)null) && !list2.Any((Player p) => (Object)(object)p.Color == (Object)(object)m))
						{
							val = m;
							break;
						}
					}
				}
				catch
				{
				}
				if ((Object)(object)val == (Object)null)
				{
					val = Object.Instantiate<Material>(list2[0].Color);
				}
				List<GameObject> list3 = new List<GameObject>();
				List<Sprite> list4 = new List<Sprite>();
				PickAbilities(list2, list3, list4);
				Player val3 = new Player(num, num2);
				val3.IsLocalPlayer = false;
				val3.UsesKeyboardAndMouse = false;
				val3.CanUseAbilities = true;
				val3.Color = val;
				val3.Abilities = list3;
				val3.AbilityIcons = list4;
				list.Add(val3);
				BoplBotTestPlugin.Log.LogInfo((object)($"[bot] joined: id={num} team={num2} color={((Object)val).name} " + "abilities=[" + string.Join(", ", list3.Select((GameObject a) => ((Object)a).name)) + "] (" + NameForDifficulty() + ")"));
			}
			catch (Exception arg)
			{
				BoplBotTestPlugin.Log.LogWarning((object)$"[bot] ADD BOT failed: {arg}");
			}
		}

		private static string NameForDifficulty()
		{
			return BoplBotTestPlugin.Difficulty.Value switch
			{
				0 => "training dummy", 
				2 => "tryhard", 
				_ => "fighter", 
			};
		}

		private static void PickAbilities(List<Player> humans, List<GameObject> abilities, List<Sprite> icons)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			NamedSpriteList abilityIcons = SteamManager.instance.abilityIcons;
			string[] array = new string[3]
			{
				BoplBotTestPlugin.Ability1.Value,
				BoplBotTestPlugin.Ability2.Value,
				BoplBotTestPlugin.Ability3.Value
			};
			if (array.Any((string s) => !string.IsNullOrWhiteSpace(s)))
			{
				string[] array2 = array;
				foreach (string text in array2)
				{
					if (!string.IsNullOrWhiteSpace(text))
					{
						int num2 = abilityIcons.IndexOf(text.Trim());
						if (num2 < 0)
						{
							BoplBotTestPlugin.Log.LogWarning((object)("[bot] ability '" + text + "' doesn't exist (see the ability list in the log)"));
							continue;
						}
						abilities.Add(abilityIcons.sprites[num2].associatedGameObject);
						icons.Add(abilityIcons.sprites[num2].sprite);
					}
				}
				if (abilities.Count > 0)
				{
					return;
				}
				BoplBotTestPlugin.Log.LogWarning((object)"[bot] no valid config abilities - falling back");
			}
			if (BoplBotTestPlugin.MirrorLoadout.Value && humans[0].Abilities != null && humans[0].Abilities.Count > 0)
			{
				abilities.AddRange(humans[0].Abilities);
				if (humans[0].AbilityIcons != null)
				{
					icons.AddRange(humans[0].AbilityIcons);
				}
				return;
			}
			List<NamedSprite> list = abilityIcons.sprites.Where((NamedSprite s) => (Object)(object)s.associatedGameObject != (Object)null).ToList();
			while (abilities.Count < 3 && list.Count > 0)
			{
				int index = Random.Range(0, list.Count);
				abilities.Add(list[index].associatedGameObject);
				icons.Add(list[index].sprite);
				list.RemoveAt(index);
			}
		}
	}
	public class BotBrain : MonoBehaviour
	{
		private enum BowState
		{
			Idle,
			Pressing,
			Charging,
			Release,
			Cooldown
		}

		private enum NadeState
		{
			Idle,
			Pressing,
			Charging,
			Release,
			Cooldown
		}

		private class QuickAbility
		{
			public string name;

			public int slot = -1;

			public Fix range;

			public Fix minRange;

			public float holdSec;

			public float cooldown;

			public bool oncePerLife;

			public bool engageAway;

			public bool needsLos;

			public bool pathCheck;

			public bool aimLead;

			public bool ignoreLock;

			public bool spent;

			public int state;

			public float timer;
		}

		private Player _bot;

		private SlimeController _slime;

		private SlimeController _lastSlime;

		private PlayerBody _body;

		private Fix _ropeRadius;

		private float _nextScan;

		private int _bowSlot = -1;

		private int _nadeSlot = -1;

		private int _hookSlot = -1;

		private int _mineSlot = -1;

		private int _holeSlot = -1;

		private int _gunSlot = -1;

		private int _missileSlot = -1;

		private int _smokeSlot = -1;

		private int _rollSlot = -1;

		private int _rockSlot = -1;

		private int _reviveSlot = -1;

		private int _dashSlot = -1;

		private bool _loadoutLogged;

		private BowTransform _myBow;

		private ThrowItem2 _myThrower;

		private float _nextAbilityScan;

		private Vec2 _aimDir = Vec2.zero;

		private Vec2 _grenadeDir = Vec2.zero;

		private bool _grenadeCanHit;

		private float _lastSolve;

		private Vec2 _lastSelfVel;

		private bool _haveSelfVel;

		private bool _lock;

		private float _lockTime;

		private Vec2 _fallbackDir = Vec2.zero;

		private BowState _bow;

		private float _bowTimer;

		private int _bowGiveups;

		private float _bowHoldUntil;

		private NadeState _nade;

		private float _nadeTimer;

		private int _grState;

		private float _grTimer;

		private Vec2 _grDir = Vec2.zero;

		private readonly QuickAbility _mine = new QuickAbility
		{
			name = "mine",
			range = (Fix)20L,
			holdSec = 0.6f,
			cooldown = 4.8f
		};

		private readonly QuickAbility _hole = new QuickAbility
		{
			name = "black hole",
			range = (Fix)18L,
			minRange = (Fix)10L,
			holdSec = 0.6f,
			cooldown = 12f,
			oncePerLife = true
		};

		private readonly QuickAbility _gun = new QuickAbility
		{
			name = "blink gun",
			range = (Fix)25L,
			holdSec = 0.45f,
			cooldown = 2.8f,
			needsLos = true,
			aimLead = true
		};

		private readonly QuickAbility _missile = new QuickAbility
		{
			name = "missile",
			range = (Fix)28L,
			holdSec = 0.45f,
			cooldown = 4.3f,
			needsLos = true
		};

		private readonly QuickAbility _smoke = new QuickAbility
		{
			name = "smoke",
			range = (Fix)18L,
			holdSec = 0.6f,
			cooldown = 3.3f
		};

		private readonly QuickAbility _roll = new QuickAbility
		{
			name = "roll",
			range = (Fix)8L,
			holdSec = 2f,
			cooldown = 3.8f,
			pathCheck = true
		};

		private readonly QuickAbility _rock = new QuickAbility
		{
			name = "rock",
			range = (Fix)4L,
			holdSec = 2.2f,
			cooldown = 5f,
			pathCheck = true
		};

		private readonly QuickAbility _revive = new QuickAbility
		{
			name = "revival",
			range = (Fix)15L,
			holdSec = 0.6f,
			cooldown = 10f,
			oncePerLife = true,
			engageAway = true,
			ignoreLock = true
		};

		private readonly QuickAbility _dash = new QuickAbility
		{
			name = "dash",
			range = (Fix)12L,
			holdSec = 0.15f,
			cooldown = 4.3f,
			pathCheck = true
		};

		private Vector2 _lastGroundedPos;

		private float _nextHazardScan;

		private readonly List<BlackHole> _moveHoles = new List<BlackHole>();

		private readonly List<BounceBall> _enemyRocks = new List<BounceBall>();

		private readonly List<Grenade> _liveNades = new List<Grenade>();

		private readonly List<Mine> _liveMines = new List<Mine>();

		private string _moveDoing = "idle";

		private Vec2 _lastMoveCheckPos;

		private float _nextMoveCheck;

		private float _unstickUntil;

		private Vec2 _lastSeenPos = Vec2.zero;

		private float _lastSeenTime = -100f;

		private bool _navNeedsJump;

		private float _nextDodgeCheck;

		private float _dodgeUntil;

		private Vec2 _dodgeDir = Vec2.right;

		private bool _outJump;

		private bool _outA1;

		private bool _outA2;

		private bool _outA3;

		private Vec2 _outDir = Vec2.zero;

		private bool _outSet;

		private float _abilityLockUntil;

		private readonly List<QuickAbility> _extras = new List<QuickAbility>();

		private static readonly (Type type, Fix range, float hold, float cd, bool los)[] Specials = new(Type, Fix, float, float, bool)[8]
		{
			(typeof(Drill), (Fix)13L, 2.4f, 6f, false),
			(typeof(TimeStop), (Fix)18L, 0.6f, 18f, false),
			(typeof(Invisibility), (Fix)14L, 0.5f, 14f, false),
			(typeof(MeteorSmash), (Fix)12L, 1.5f, 8f, false),
			(typeof(MagnetGun), (Fix)14L, 0.7f, 5f, true),
			(typeof(Katana), (Fix)6L, 0.5f, 4f, true),
			(typeof(StretchableLightning), (Fix)15L, 0.5f, 4.5f, true),
			(typeof(ThrowFireball), (Fix)20L, 0.5f, 3.5f, true)
		};

		private static readonly Fix[] NavAngles = (Fix[])(object)new Fix[7]
		{
			(Fix)0L,
			(Fix)0.44,
			(Fix)(-0.44),
			(Fix)0.87,
			(Fix)(-0.87),
			(Fix)1.57,
			(Fix)(-1.57)
		};

		private int Diff => BoplBotTestPlugin.Difficulty.Value;

		private Fix RangeScale
		{
			get
			{
				//IL_0012: 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_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				if (Diff < 2)
				{
					return Fix.One;
				}
				return (Fix)125L / (Fix)100L;
			}
		}

		private float CdScale
		{
			get
			{
				if (Diff < 2)
				{
					return 1f;
				}
				return 0.65f;
			}
		}

		private bool Fights => Diff >= 1;

		private float AbilityGap
		{
			get
			{
				if (Diff < 2)
				{
					return 1.2f;
				}
				return 0.8f;
			}
		}

		internal void AssignBot(Player p)
		{
			if (p != _bot)
			{
				_bot = p;
				_slime = null;
				_body = null;
				ResetAll();
			}
		}

		private void Awake()
		{
		}

		private void Update()
		{
			ResetOutputs();
			if (_bot == null)
			{
				return;
			}
			List<Player> list = null;
			try
			{
				PlayerHandler obj = PlayerHandler.Get();
				list = ((obj != null) ? obj.PlayerList() : null);
			}
			catch
			{
			}
			if (list == null || !list.Contains(_bot))
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if ((Object)(object)_body == (Object)null || unscaledTime >= _nextScan)
			{
				_nextScan = unscaledTime + 1.5f;
				ScanSlime();
			}
			if ((Object)(object)_body == (Object)null)
			{
				PushInputs();
				return;
			}
			if ((Object)(object)_slime != (Object)null && _slime.HasSpawned && !GameSessionHandler.HasGameEnded())
			{
				try
				{
					Think(unscaledTime);
				}
				catch
				{
				}
			}
			PushInputs();
		}

		private void ResetOutputs()
		{
			//IL_0023: 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)
			_outJump = (_outA1 = (_outA2 = (_outA3 = false)));
			_outDir = Vec2.zero;
			_outSet = false;
		}

		private void PushInputs()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (_bot == null)
			{
				return;
			}
			try
			{
				byte b = InputProfile.JoyStickAngleByteFromVector(_outDir);
				_bot.ForceSetInputProfile(false, false, _outJump, _outA1, _outA2, _outA3, b, false, false, false, false);
			}
			catch
			{
			}
		}

		internal void ResetAll()
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			_bow = BowState.Idle;
			_nade = NadeState.Idle;
			_grState = 0;
			_mine.state = (_hole.state = (_gun.state = (_missile.state = 0)));
			_smoke.state = (_roll.state = (_rock.state = (_revive.state = (_dash.state = 0))));
			_loadoutLogged = false;
			_myBow = null;
			_myThrower = null;
			_haveSelfVel = false;
			_lastGroundedPos = default(Vector2);
			_unstickUntil = 0f;
			_abilityLockUntil = 0f;
			_fallbackDir = Vec2.zero;
			_lastMoveCheckPos = Vec2.zero;
			_nextMoveCheck = 0f;
			_dodgeUntil = 0f;
			_nextDodgeCheck = 0f;
			_lastSeenPos = Vec2.zero;
			_lastSeenTime = -100f;
			_extras.Clear();
			_outSet = false;
		}

		private void ScanSlime()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				SlimeController[] array = Object.FindObjectsOfType<SlimeController>();
				foreach (SlimeController val in array)
				{
					if ((Object)(object)val == (Object)null || val.GetPlayerId() != _bot.Id)
					{
						continue;
					}
					_slime = val;
					_body = val.body;
					if ((Object)(object)val != (Object)(object)_lastSlime)
					{
						_loadoutLogged = false;
						_lastSlime = val;
						ResetMachines();
					}
					try
					{
						_ropeRadius = val.RopeCircleCastRadius;
					}
					catch
					{
					}
					_bowSlot = (_nadeSlot = (_hookSlot = -1));
					_mineSlot = (_holeSlot = (_gunSlot = (_missileSlot = -1)));
					_smokeSlot = (_rollSlot = (_rockSlot = (_reviveSlot = (_dashSlot = -1))));
					bool[] array2 = new bool[val.abilities.Count];
					for (int j = 0; j < val.abilities.Count; j++)
					{
						AbilityMonoBehaviour val2 = val.abilities[j];
						if ((Object)(object)val2 == (Object)null)
						{
							continue;
						}
						if (_bowSlot < 0 && (Object)(object)((Component)val2).GetComponent<BowTransform>() != (Object)null)
						{
							_bowSlot = j;
							array2[j] = true;
						}
						if (_nadeSlot < 0 && (Object)(object)((Component)val2).GetComponent<ThrowItem2>() != (Object)null)
						{
							_nadeSlot = j;
							array2[j] = true;
						}
						if (_hookSlot < 0 && (Object)(object)((Component)val2).GetComponent<HookshotInstant>() != (Object)null)
						{
							_hookSlot = j;
							array2[j] = true;
						}
						if (_mineSlot < 0 && (Object)(object)((Component)val2).GetComponent<ThrowItem>() != (Object)null)
						{
							try
							{
								BoplBody value = new Traverse((object)((Component)val2).GetComponent<ThrowItem>()).Field<BoplBody>("GrenadePrefab").Value;
								if (!((Object)(object)value == (Object)null))
								{
									if ((Object)(object)((Component)value).GetComponent<Mine>() != (Object)null)
									{
										_mineSlot = j;
										array2[j] = true;
									}
									else if ((Object)(object)((Component)value).GetComponent<FlammableSmoke>() != (Object)null)
									{
										_smokeSlot = j;
										array2[j] = true;
									}
								}
							}
							catch
							{
							}
						}
						if (_holeSlot < 0 && (Object)(object)((Component)val2).GetComponent<BlackHoleClap>() != (Object)null)
						{
							_holeSlot = j;
							array2[j] = true;
						}
						if (_gunSlot < 0 && (Object)(object)((Component)val2).GetComponent<GunTransform>() != (Object)null)
						{
							_gunSlot = j;
							array2[j] = true;
						}
						if (_missileSlot < 0 && (Object)(object)((Component)val2).GetComponent<SparkShot>() != (Object)null)
						{
							_missileSlot = j;
							array2[j] = true;
						}
						if (_rollSlot < 0 && (Object)(object)((Component)val2).GetComponent<Roll>() != (Object)null)
						{
							_rollSlot = j;
							array2[j] = true;
						}
						if (_rockSlot < 0 && (Object)(object)((Component)val2).GetComponent<BounceBall>() != (Object)null)
						{
							_rockSlot = j;
							array2[j] = true;
						}
						if (_reviveSlot < 0 && (Object)(object)((Component)val2).GetComponent<Revive>() != (Object)null)
						{
							_reviveSlot = j;
							array2[j] = true;
						}
						if (_dashSlot < 0 && (Object)(object)((Component)val2).GetComponent<Dash>() != (Object)null)
						{
							_dashSlot = j;
							array2[j] = true;
						}
					}
					_mine.slot = _mineSlot;
					_hole.slot = _holeSlot;
					_gun.slot = _gunSlot;
					_missile.slot = _missileSlot;
					_smoke.slot = _smokeSlot;
					_roll.slot = _rollSlot;
					_rock.slot = _rockSlot;
					_revive.slot = _reviveSlot;
					_dash.slot = _dashSlot;
					_extras.Clear();
					for (int k = 0; k < val.abilities.Count; k++)
					{
						if (!array2[k])
						{
							AbilityMonoBehaviour val3 = val.abilities[k];
							if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((Component)val3).GetComponent<NullAbility>() != (Object)null))
							{
								QuickAbility quickAbility = SpecialConfig((Component)(object)val3) ?? new QuickAbility
								{
									name = "generic",
									range = (Fix)14L,
									holdSec = 0.5f,
									cooldown = 4f + 0.6f * (float)_extras.Count
								};
								quickAbility.slot = k;
								_extras.Add(quickAbility);
								BoplBotTestPlugin.Log.LogInfo((object)$"[bot] ability slot {k} now driven: {quickAbility.name}");
							}
						}
					}
					if (!_loadoutLogged)
					{
						_loadoutLogged = true;
						for (int l = 0; l < val.abilities.Count; l++)
						{
							BoplBotTestPlugin.Log.LogInfo((object)$"[bot] loadout slot {l}: {IdentifyAbility((Component)(object)val.abilities[l])}");
						}
					}
					return;
				}
				_slime = null;
				_body = null;
			}
			catch
			{
				_slime = null;
				_body = null;
			}
		}

		private void ResetMachines()
		{
			_bow = BowState.Idle;
			_nade = NadeState.Idle;
			_grState = 0;
			_mine.state = (_hole.state = (_gun.state = (_missile.state = 0)));
			_smoke.state = (_roll.state = (_rock.state = (_revive.state = (_dash.state = 0))));
			for (int i = 0; i < _extras.Count; i++)
			{
				_extras[i].state = 0;
			}
		}

		private string IdentifyAbility(Component ab)
		{
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)ab.GetComponent<BowTransform>() != (Object)null)
				{
					return "BOW";
				}
				if ((Object)(object)ab.GetComponent<ThrowItem2>() != (Object)null)
				{
					return "GRENADE";
				}
				if ((Object)(object)ab.GetComponent<HookshotInstant>() != (Object)null)
				{
					return "GRAPPLE";
				}
				if ((Object)(object)ab.GetComponent<BlackHoleClap>() != (Object)null)
				{
					return "BLACK HOLE";
				}
				if ((Object)(object)ab.GetComponent<SparkShot>() != (Object)null)
				{
					return "MISSILE";
				}
				if ((Object)(object)ab.GetComponent<GunTransform>() != (Object)null)
				{
					return "GUN-FAMILY";
				}
				if ((Object)(object)ab.GetComponent<Roll>() != (Object)null)
				{
					return "ROLL";
				}
				if ((Object)(object)ab.GetComponent<BounceBall>() != (Object)null)
				{
					return "ROCK";
				}
				if ((Object)(object)ab.GetComponent<Revive>() != (Object)null)
				{
					return "REVIVAL";
				}
				if ((Object)(object)ab.GetComponent<Dash>() != (Object)null)
				{
					return "DASH";
				}
				if ((Object)(object)ab.GetComponent<ThrowItem>() != (Object)null)
				{
					string text = "?";
					try
					{
						BoplBody value = new Traverse((object)ab.GetComponent<ThrowItem>()).Field<BoplBody>("GrenadePrefab").Value;
						if ((Object)(object)value != (Object)null)
						{
							text = ((Object)value).name;
						}
					}
					catch
					{
					}
					return "THROW-ITEM (prefab: " + text + ")";
				}
				StringBuilder stringBuilder = new StringBuilder("UNKNOWN - components: ");
				MonoBehaviour[] components = ab.GetComponents<MonoBehaviour>();
				foreach (MonoBehaviour val in components)
				{
					if (!((Object)(object)val == (Object)null))
					{
						stringBuilder.Append(((object)val).GetType().Name);
						stringBuilder.Append(", ");
					}
				}
				return stringBuilder.ToString();
			}
			catch
			{
				return "?";
			}
		}

		private void ScanAbilities()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			_myBow = null;
			_myThrower = null;
			try
			{
				BowTransform[] array = Resources.FindObjectsOfTypeAll<BowTransform>();
				Scene scene;
				foreach (BowTransform val in array)
				{
					if (!((Object)(object)val == (Object)null))
					{
						scene = ((Component)val).gameObject.scene;
						if (((Scene)(ref scene)).IsValid() && new Traverse((object)val).Field<PlayerInfo>("playerInfo").Value.playerId == _bot.Id)
						{
							_myBow = val;
							break;
						}
					}
				}
				ThrowItem2[] array2 = Resources.FindObjectsOfTypeAll<ThrowItem2>();
				foreach (ThrowItem2 val2 in array2)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						scene = ((Component)val2).gameObject.scene;
						if (((Scene)(ref scene)).IsValid() && new Traverse((object)val2).Field<PlayerInfo>("playerInfo").Value.playerId == _bot.Id)
						{
							_myThrower = val2;
							break;
						}
					}
				}
			}
			catch
			{
			}
		}

		private void Think(float now)
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if (now >= _nextAbilityScan)
			{
				_nextAbilityScan = now + 1f;
				ScanAbilities();
			}
			bool num = Fights && _bowSlot >= 0;
			bool flag = Fights && _nadeSlot >= 0;
			if ((num || flag) && now - _lastSolve > 0.06f)
			{
				bool flag2 = false;
				try
				{
					Vec2 selfImposedVelocity = _body.selfImposedVelocity;
					if (_haveSelfVel && Vec2.Magnitude(selfImposedVelocity - _lastSelfVel) > (Fix)0.5)
					{
						flag2 = true;
					}
					_lastSelfVel = selfImposedVelocity;
					_haveSelfVel = true;
				}
				catch
				{
				}
				if (now - _lastSolve > 0.06f || flag2)
				{
					_lastSolve = now;
					if (_bow == BowState.Charging)
					{
						_aimDir = SolveAimDir(_body, BowFirePoint(), BowSpeed());
					}
					else if (_nade == NadeState.Charging)
					{
						_grenadeDir = SolveThrowDir();
					}
				}
			}
			if (Fights)
			{
				if (_hookSlot >= 0)
				{
					GrappleTick();
				}
				if (!_outSet && _hole.slot >= 0)
				{
					QuickTick(_hole);
				}
				if (!_outSet && _roll.slot >= 0)
				{
					QuickTick(_roll);
				}
				if (!_outSet && _rock.slot >= 0)
				{
					QuickTick(_rock);
				}
				if (!_outSet && _bowSlot >= 0)
				{
					BowTick();
				}
				if (!_outSet && _gun.slot >= 0)
				{
					QuickTick(_gun);
				}
				if (!_outSet && _missile.slot >= 0)
				{
					QuickTick(_missile);
				}
				if (!_outSet && _mine.slot >= 0)
				{
					QuickTick(_mine);
				}
				if (!_outSet && _smoke.slot >= 0)
				{
					QuickTick(_smoke);
				}
				if (!_outSet && _nadeSlot >= 0)
				{
					NadeTick();
				}
				if (!_outSet && _dash.slot >= 0)
				{
					QuickTick(_dash);
				}
				if (!_outSet && _revive.slot >= 0)
				{
					QuickTick(_revive);
				}
				int num2 = 0;
				while (!_outSet && num2 < _extras.Count)
				{
					if (_extras[num2].slot >= 0)
					{
						QuickTick(_extras[num2]);
					}
					num2++;
				}
			}
			if (!_outSet)
			{
				MoveTick();
			}
		}

		private void Drive(int slot, bool pressed, Vec2 dir)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			_outSet = true;
			switch (slot)
			{
			case 0:
				_outA1 = pressed;
				break;
			case 1:
				_outA2 = pressed;
				break;
			case 2:
				_outA3 = pressed;
				break;
			}
			_outDir = ((Vec2.Magnitude(dir) > (Fix)0.01) ? dir : _outDir);
		}

		private void MoveDrive(Vec2 dir, bool jump)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			_outSet = true;
			_outDir = ((Vec2.Magnitude(dir) > (Fix)0.01) ? dir : _outDir);
			if (jump)
			{
				_outJump = true;
			}
		}

		private Vec2 BowFirePoint()
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_myBow == (Object)null)
			{
				return Vec2.zero;
			}
			try
			{
				Traverse val = new Traverse((object)_myBow);
				PlayerBody value = val.Field<PlayerBody>("body").Value;
				if ((Object)(object)value == (Object)null)
				{
					return Vec2.zero;
				}
				return value.position + val.Field<Vec2>("FirepointOffset").Value.x * value.right + val.Field<Vec2>("FirepointOffset").Value.y * value.up;
			}
			catch
			{
				return Vec2.zero;
			}
		}

		private Fix BowSpeed()
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_myBow == (Object)null || (Object)(object)_body == (Object)null)
			{
				return (Fix)10L;
			}
			try
			{
				Traverse val = new Traverse((object)_myBow);
				Fix val2 = Fix.One + (_body.fixtrans.Scale - Fix.One) / (Fix)2L;
				return ((Fix)(long)val.Field<int>("loadingFrame").Value + Fix.One) * val.Field<Fix>("ArrowSpeed").Value * val2;
			}
			catch
			{
				return (Fix)10L;
			}
		}

		private void BowTick()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			switch (_bow)
			{
			case BowState.Idle:
				if (AnyEnemy() && !(Time.unscaledTime < _bowHoldUntil) && IsReallyReady(_bowSlot) && HasLosToNearestEnemy())
				{
					_bow = BowState.Pressing;
					_bowTimer = Time.unscaledTime;
				}
				break;
			case BowState.Pressing:
				Drive(_bowSlot, pressed: true, _aimDir);
				if (Time.unscaledTime - _bowTimer > 0.1f)
				{
					_bow = BowState.Charging;
					_bowTimer = Time.unscaledTime;
				}
				break;
			case BowState.Charging:
			{
				Drive(_bowSlot, pressed: true, _aimDir);
				int num2 = 0;
				try
				{
					if ((Object)(object)_myBow != (Object)null)
					{
						num2 = new Traverse((object)_myBow).Field<int>("loadingFrame").Value;
					}
				}
				catch
				{
				}
				if (Time.unscaledTime - _bowTimer > 0.7f && !HasLosToNearestEnemy())
				{
					_bowGiveups++;
					_bow = BowState.Cooldown;
					_bowTimer = Time.unscaledTime;
					break;
				}
				bool flag = _lock && Time.unscaledTime - _lockTime < 0.5f;
				if (num2 >= 2 && flag)
				{
					_bowGiveups = 0;
					_abilityLockUntil = Time.unscaledTime + AbilityGap;
					_bow = BowState.Release;
					_bowTimer = Time.unscaledTime;
				}
				else if (num2 >= 2 && Time.unscaledTime - _bowTimer > 1.4f && Vec2.Magnitude(_fallbackDir) > (Fix)0.01)
				{
					_aimDir = _fallbackDir;
					_abilityLockUntil = Time.unscaledTime + AbilityGap;
					_bow = BowState.Release;
					_bowTimer = Time.unscaledTime;
				}
				else if (Time.unscaledTime - _bowTimer > 4f)
				{
					_bowGiveups++;
					_bow = BowState.Cooldown;
					_bowTimer = Time.unscaledTime;
				}
				break;
			}
			case BowState.Release:
				Drive(_bowSlot, pressed: false, _aimDir);
				if (Time.unscaledTime - _bowTimer > 0.15f)
				{
					_bow = BowState.Cooldown;
					_bowTimer = Time.unscaledTime;
				}
				break;
			case BowState.Cooldown:
			{
				float num = ((_bowGiveups >= 2) ? 3.5f : 1.6f);
				if (Time.unscaledTime - _bowTimer > num)
				{
					_bow = BowState.Idle;
					_bowHoldUntil = Time.unscaledTime + ((_bowGiveups >= 2) ? 1.5f : 0f);
				}
				break;
			}
			}
		}

		private void NadeTick()
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			switch (_nade)
			{
			case NadeState.Idle:
				if (AnyEnemy() && IsReallyReady(_nadeSlot) && EnemyWithin((Fix)30L) && !EnemyWithin((Fix)7L) && HasLosToNearestEnemy())
				{
					_nade = NadeState.Pressing;
					_nadeTimer = Time.unscaledTime;
				}
				break;
			case NadeState.Pressing:
				Drive(_nadeSlot, pressed: true, _grenadeDir);
				if (Time.unscaledTime - _nadeTimer > 0.1f)
				{
					_nade = NadeState.Charging;
					_nadeTimer = Time.unscaledTime;
				}
				break;
			case NadeState.Charging:
				Drive(_nadeSlot, pressed: true, _grenadeDir);
				if (_grenadeCanHit && Time.unscaledTime - _nadeTimer > 0.25f)
				{
					_nade = NadeState.Release;
					_nadeTimer = Time.unscaledTime;
				}
				else if (Time.unscaledTime - _nadeTimer > 3.5f)
				{
					_nade = NadeState.Release;
					_nadeTimer = Time.unscaledTime;
				}
				break;
			case NadeState.Release:
				Drive(_nadeSlot, pressed: false, _grenadeDir);
				if (Time.unscaledTime - _nadeTimer > 0.15f)
				{
					_abilityLockUntil = Time.unscaledTime + AbilityGap;
					_nade = NadeState.Cooldown;
					_nadeTimer = Time.unscaledTime;
				}
				break;
			case NadeState.Cooldown:
				if (Time.unscaledTime - _nadeTimer > 3.5f * CdScale)
				{
					_nade = NadeState.Idle;
				}
				break;
			}
		}

		private void GrappleTick()
		{
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: 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_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			switch (_grState)
			{
			case 0:
			{
				PlayerBody val = null;
				try
				{
					float num = ((_ropeRadius > Fix.Zero) ? ((float)(double)_ropeRadius) : 2f);
					PlayerBody[] array = Object.FindObjectsOfType<PlayerBody>();
					foreach (PlayerBody val2 in array)
					{
						if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)_body) && Vector2.Distance(Vector2.op_Implicit(((Component)_body).transform.position), Vector2.op_Implicit(((Component)val2).transform.position)) < num)
						{
							val = val2;
							break;
						}
					}
				}
				catch
				{
				}
				if ((Object)(object)val == (Object)null || !IsReallyReady(_hookSlot))
				{
					break;
				}
				Vec2 grDir = Vec2.down;
				try
				{
					BlackHole[] array2 = Object.FindObjectsOfType<BlackHole>();
					foreach (BlackHole val3 in array2)
					{
						if ((Object)(object)val3 == (Object)null)
						{
							continue;
						}
						Vector3 position = ((Component)val3).transform.position;
						if (Vector2.Distance(Vector2.op_Implicit(position), Vector2.op_Implicit(((Component)val).transform.position)) < 12f)
						{
							Vec2 val4 = Vec2.right * (Fix)(position.x - ((Component)val).transform.position.x) + Vec2.up * (Fix)(position.y - ((Component)val).transform.position.y);
							if (Vec2.Magnitude(val4) > (Fix)0.1)
							{
								grDir = Vec2.NormalizedSafe(val4);
							}
							break;
						}
					}
				}
				catch
				{
				}
				_grDir = grDir;
				_grState = 1;
				_grTimer = Time.unscaledTime;
				break;
			}
			case 1:
				Drive(_hookSlot, pressed: true, _grDir);
				if (Time.unscaledTime - _grTimer > 0.08f)
				{
					_grState = 2;
					_grTimer = Time.unscaledTime;
				}
				break;
			case 2:
				Drive(_hookSlot, pressed: false, _grDir);
				if (Time.unscaledTime - _grTimer > 0.08f)
				{
					_abilityLockUntil = Time.unscaledTime + AbilityGap;
					_grState = 3;
					_grTimer = Time.unscaledTime;
				}
				break;
			case 3:
				if (Time.unscaledTime - _grTimer > 3.5f * CdScale)
				{
					_grState = 0;
					_grDir = Vec2.zero;
				}
				break;
			}
		}

		private static QuickAbility SpecialConfig(Component ab)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			(Type, Fix, float, float, bool)[] specials = Specials;
			for (int i = 0; i < specials.Length; i++)
			{
				(Type, Fix, float, float, bool) tuple = specials[i];
				try
				{
					if ((Object)(object)ab.GetComponent(tuple.Item1) != (Object)null)
					{
						QuickAbility quickAbility = new QuickAbility
						{
							name = tuple.Item1.Name.ToLower(),
							range = tuple.Item2,
							holdSec = tuple.Item3,
							cooldown = tuple.Item4,
							needsLos = tuple.Item5
						};
						if (tuple.Item1 == typeof(TimeStop))
						{
							quickAbility.ignoreLock = true;
						}
						return quickAbility;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private void QuickTick(QuickAbility qa)
		{
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			switch (qa.state)
			{
			case 0:
			{
				if (qa.slot < 0 || (qa.oncePerLife && qa.spent) || (!qa.ignoreLock && Time.unscaledTime < _abilityLockUntil))
				{
					break;
				}
				PlayerBody val = NearestEnemyBody();
				Fix val2 = (((Object)(object)val != (Object)null) ? Vec2.Magnitude(val.position - _body.position) : Fix.MaxValue);
				bool flag = val2 < qa.range * RangeScale;
				if (qa.engageAway)
				{
					if (flag)
					{
						break;
					}
				}
				else if (!flag || val2 < qa.minRange)
				{
					break;
				}
				if ((!qa.needsLos || HasLosToNearestEnemy()) && (!qa.pathCheck || MovementPathSafe()) && IsReallyReady(qa.slot))
				{
					qa.state = 1;
					qa.timer = Time.unscaledTime;
				}
				break;
			}
			case 1:
				Drive(qa.slot, pressed: true, qa.aimLead ? LeadAim((Fix)30L) : AimAtNearestEnemy());
				if (Time.unscaledTime - qa.timer > qa.holdSec)
				{
					qa.state = 2;
					qa.timer = Time.unscaledTime;
				}
				break;
			case 2:
				Drive(qa.slot, pressed: false, qa.aimLead ? LeadAim((Fix)30L) : AimAtNearestEnemy());
				if (Time.unscaledTime - qa.timer > 0.1f)
				{
					if (qa.oncePerLife)
					{
						qa.spent = true;
					}
					if (!qa.ignoreLock)
					{
						_abilityLockUntil = Time.unscaledTime + AbilityGap;
					}
					qa.state = 3;
					qa.timer = Time.unscaledTime;
				}
				break;
			case 3:
				if (Time.unscaledTime - qa.timer > qa.cooldown * CdScale)
				{
					qa.state = 0;
				}
				break;
			}
		}

		private static Vec2 ToVec2(Vector2 v)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			return Vec2.right * (Fix)v.x + Vec2.up * (Fix)v.y;
		}

		private void MoveTick()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_044b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			//IL_0455: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_045b: Unknown result type (might be due to invalid IL or missing references)
			//IL_059e: Unknown result type (might be due to invalid IL or missing references)
			//IL_059f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0467: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_047e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Unknown result type (might be due to invalid IL or missing ref