Decompiled source of BubbleGum v1.0.0

BubbleGum.dll

Decompiled 21 minutes ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using BoplFixedMath;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BubbleGum")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A Bopl Battle ability: throw a bubblegum ball that ricochets off everything it touches and pops on the fourth contact.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a8453e11475d9ea3fa0b40f6176d348f4814c716")]
[assembly: AssemblyProduct("BubbleGum")]
[assembly: AssemblyTitle("BubbleGum")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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 BubbleGum
{
	public static class BubbleAbility
	{
		public const string AbilityName = "bubblegum";

		public const string TemplateNameFragment = "grenade";

		public const float CooldownSeconds = 3.9f;

		public static readonly Fix Speed = (Fix)34L;

		public static readonly Fix Radius = (Fix)1.7;

		public const float BubbleWorldWidth = 3.4f;

		public const int MaxContacts = 4;

		public const int OwnerGraceTicks = 45;

		public const int MaxLifeTicks = 900;

		public static readonly Fix BounceClearance = (Fix)0.2;

		public static readonly Fix ObjectReach = (Fix)0.6;

		public const float SpinDegreesPerTick = 6f;

		public static readonly Fix BlackHoleSwallowRadius = (Fix)1L;

		public static readonly Fix BlackHolePull = (Fix)0.35;

		public static readonly Fix FallbackBlackHoleMass = (Fix)1L;

		public static readonly Color GumColour = new Color(0.97f, 0.48f, 0.72f, 1f);

		public static bool IsBubbleGum(GameObject go)
		{
			if ((Object)(object)go != (Object)null)
			{
				return ((Object)go).name.ToLower().Contains("bubblegum");
			}
			return false;
		}

		public static Sprite LoadIcon(Sprite template)
		{
			//IL_0026: 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_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)
			Texture2D val = LoadTexture("BubbleGum.AbilityIcon.png");
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			float pixelsPerUnit = 100f;
			if ((Object)(object)template != (Object)null)
			{
				Rect rect = template.rect;
				if (((Rect)(ref rect)).width > 0f)
				{
					float pixelsPerUnit2 = template.pixelsPerUnit;
					float num = ((Texture)val).width;
					rect = template.rect;
					pixelsPerUnit = pixelsPerUnit2 * (num / ((Rect)(ref rect)).width);
				}
			}
			return Build(val, pixelsPerUnit);
		}

		public static Sprite LoadBubble()
		{
			Texture2D val = LoadTexture("BubbleGum.Bubble.png");
			if (!((Object)(object)val == (Object)null))
			{
				return Build(val, (float)((Texture)val).width / 3.4f);
			}
			return null;
		}

		private static Sprite Build(Texture2D texture, float pixelsPerUnit)
		{
			//IL_0019: 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)
			return Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f), pixelsPerUnit);
		}

		private static Texture2D LoadTexture(string resourceName)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
			if (stream == null)
			{
				Plugin.Log.LogError((object)("Bubble Gum: embedded resource '" + resourceName + "' not found."));
				return null;
			}
			byte[] array;
			using (MemoryStream memoryStream = new MemoryStream())
			{
				stream.CopyTo(memoryStream);
				array = memoryStream.ToArray();
			}
			Texture2D val = new Texture2D(1, 1);
			if (!ImageConversion.LoadImage(val, array))
			{
				Plugin.Log.LogError((object)("Bubble Gum: '" + resourceName + "' failed to decode as a PNG."));
				return null;
			}
			return val;
		}
	}
	[HarmonyPatch(typeof(AbilityGrid), "Awake")]
	public static class BubbleInjectionPatch
	{
		private static bool hasInjected;

		public static void Prefix(AbilityGrid __instance)
		{
			//IL_0032: 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)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			if (hasInjected)
			{
				return;
			}
			NamedSpriteList abilityIcons = __instance.abilityIcons;
			if ((Object)(object)abilityIcons == (Object)null || abilityIcons.sprites == null)
			{
				Plugin.Log.LogWarning((object)"Bubble Gum: AbilityGrid.abilityIcons was empty this Awake; not injecting yet (will retry on the next grid build).");
				return;
			}
			NamedSprite val = default(NamedSprite);
			bool flag = false;
			foreach (NamedSprite sprite in abilityIcons.sprites)
			{
				if (sprite.name != null && sprite.name.ToLower().Contains("grenade"))
				{
					val = sprite;
					flag = true;
					break;
				}
			}
			if (!flag || (Object)(object)val.associatedGameObject == (Object)null)
			{
				Plugin.Log.LogError((object)"Bubble Gum: could not find the native grenade ability to clone, so the bubble was not added. (Looked for an ability whose name contains 'grenade'.)");
				return;
			}
			GameObject val2 = Object.Instantiate<GameObject>(val.associatedGameObject);
			Object.DontDestroyOnLoad((Object)(object)val2);
			((Object)val2).name = "bubblegum";
			Ability component = val2.GetComponent<Ability>();
			if ((Object)(object)component == (Object)null)
			{
				Plugin.Log.LogError((object)"Bubble Gum: the clone has no Ability component, so its cooldown could not be set; it keeps the grenade's.");
			}
			else
			{
				component.Cooldown = (Fix)3.9f;
			}
			SwapInHandSprite(val2);
			Sprite val3 = BubbleAbility.LoadIcon(val.sprite) ?? val.sprite;
			abilityIcons.sprites.Add(new NamedSprite("bubblegum", val3, val2, true));
			hasInjected = true;
			Plugin.Log.LogInfo((object)("Bubble Gum: ability injected into the select grid (cloned " + $"'{val.name}', reload {3.9f}s, pops on " + $"contact {4})."));
		}

		private static void SwapInHandSprite(GameObject clone)
		{
			if (clone.transform.childCount <= 1)
			{
				Plugin.Log.LogInfo((object)"Bubble Gum: the clone has no in-hand dummy, so it may still look like a grenade while you aim.");
				return;
			}
			SpriteRenderer componentInChildren = ((Component)clone.transform.GetChild(1)).GetComponentInChildren<SpriteRenderer>(true);
			if ((Object)(object)componentInChildren == (Object)null)
			{
				Plugin.Log.LogInfo((object)"Bubble Gum: no sprite on the in-hand dummy, so it may still look like a grenade while you aim.");
				return;
			}
			Sprite val = BubbleVisuals.BubbleSprite();
			if ((Object)(object)val != (Object)null)
			{
				componentInChildren.sprite = val;
			}
		}
	}
	[HarmonyPatch(typeof(ThrowItem2), "SpawnGrenade")]
	public static class BubbleAppearancePatch
	{
		public static void Postfix(ThrowItem2 __instance)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if (!BubbleAbility.IsBubbleGum(((Component)__instance).gameObject))
			{
				return;
			}
			BoplBody value = Traverse.Create((object)__instance).Field("grenadeBody").GetValue<BoplBody>();
			if ((Object)(object)value == (Object)null)
			{
				return;
			}
			GrenadeExplode component = ((Component)value).GetComponent<GrenadeExplode>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			Grenade component2 = ((Component)value).GetComponent<Grenade>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.timedExplosion = false;
				component2.selfDestructDelay = -Fix.One;
			}
			SpriteRenderer componentInChildren = ((Component)value).GetComponentInChildren<SpriteRenderer>();
			if ((Object)(object)componentInChildren == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Bubble Gum: the in-hand body has no SpriteRenderer, so it still looks like a grenade while you aim.");
				return;
			}
			Sprite val = BubbleVisuals.BubbleSprite();
			if ((Object)(object)val != (Object)null)
			{
				componentInChildren.sprite = val;
			}
		}
	}
	[HarmonyPatch(typeof(ThrowItem2), "ExitAbility", new Type[] { typeof(AbilityExitInfo) })]
	public static class BubbleNoDropPatch
	{
		public static void Prefix(ThrowItem2 __instance)
		{
			if (!BubbleAbility.IsBubbleGum(((Component)__instance).gameObject))
			{
				return;
			}
			Traverse val = Traverse.Create((object)__instance);
			if (!val.Field("hasFired").GetValue<bool>())
			{
				BoplBody value = val.Field("grenadeBody").GetValue<BoplBody>();
				if ((Object)(object)value != (Object)null && !((MonoUpdatable)value).IsDestroyed)
				{
					Updater.DestroyFix(((Component)value).gameObject);
					Plugin.Log.LogInfo((object)"Bubble Gum: the throw was cancelled, so the item was removed rather than dropped.");
				}
				val.Field("grenade").SetValue((object)null);
				val.Field("grenadeBody").SetValue((object)null);
			}
		}
	}
	[HarmonyPatch(typeof(ThrowItem2), "Fire")]
	public static class BubbleReleasePatch
	{
		public static void Postfix(ThrowItem2 __instance)
		{
			//IL_0036: 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_0082: 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)
			if (!BubbleAbility.IsBubbleGum(((Component)__instance).gameObject))
			{
				return;
			}
			Ability component = ((Component)__instance).GetComponent<Ability>();
			if ((Object)(object)component == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Bubble Gum: the thrower has no Ability component, so no bubble was thrown.");
				return;
			}
			int playerId = component.GetPlayerId();
			int abilityButtonUsedIndex = component.GetPlayerInfo().AbilityButtonUsedIndex012;
			long key = BubbleRegistry.KeyFor(playerId, abilityButtonUsedIndex);
			PlayerHandler val = PlayerHandler.Get();
			Player val2 = ((val == null) ? null : val.GetPlayer(playerId));
			if (val2 != null)
			{
				Traverse obj = Traverse.Create((object)__instance);
				BubbleState.Throw(aim: obj.Field("dir").GetValue<Vec2>(), playerId: playerId, key: key, origin: val2.Position);
				BubbleRegistry.Thrown(key);
				BoplBody value = obj.Field("grenadeBody").GetValue<BoplBody>();
				if ((Object)(object)value != (Object)null && !((MonoUpdatable)value).IsDestroyed)
				{
					Updater.DestroyFix(((Component)value).gameObject);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Updater), "TickSimulation")]
	public static class BubbleTickPatch
	{
		public static void Postfix()
		{
			BubbleState.Tick();
			BubbleRegistry.PinCooldownsWhileDeployed();
		}
	}
	[HarmonyPatch(typeof(PlayerHandler), "ResetForNextStage")]
	public static class BubbleResetPatch
	{
		public static void Prefix()
		{
			PlayerBodies.ForgetAll();
			BubbleRound.Clear();
		}
	}
	[HarmonyPatch(typeof(Updater), "PreLevelLoad")]
	public static class BubbleLevelLoadPatch
	{
		public static void Prefix()
		{
			BubbleRound.Clear();
		}
	}
	internal static class BubbleRound
	{
		public static void Clear()
		{
			BubbleState.ClearAll();
			BubbleRegistry.ClearAll();
		}
	}
	public static class BubbleRegistry
	{
		private static readonly HashSet<long> deployed = new HashSet<long>();

		private static readonly Dictionary<int, SlimeController> controllers = new Dictionary<int, SlimeController>();

		public static long KeyFor(int playerId, int abilityIndex)
		{
			return (long)playerId * 16L + abilityIndex;
		}

		private static int PlayerOf(long key)
		{
			return (int)(key / 16);
		}

		private static int SlotOf(long key)
		{
			return (int)(key % 16);
		}

		public static void Thrown(long key)
		{
			deployed.Add(key);
		}

		public static void BubbleGone(long key)
		{
			if (deployed.Remove(key))
			{
				ZeroCooldown(key);
				Plugin.Log.LogInfo((object)($"Bubble Gum: player {PlayerOf(key)}'s bubble is gone; the reload " + "starts now."));
			}
		}

		public static void PinCooldownsWhileDeployed()
		{
			if (deployed.Count == 0)
			{
				return;
			}
			foreach (long item in new List<long>(deployed))
			{
				if (!BubbleState.HasBubble(item))
				{
					deployed.Remove(item);
				}
				else
				{
					ZeroCooldown(item);
				}
			}
		}

		private static void ZeroCooldown(long key)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			SlimeController val = ControllerFor(PlayerOf(key));
			if (!((Object)(object)val == (Object)null))
			{
				Fix[] value = Traverse.Create((object)val).Field("abilityCooldownTimers").GetValue<Fix[]>();
				int num = SlotOf(key);
				if (value != null && num >= 0 && num < value.Length)
				{
					value[num] = Fix.Zero;
				}
			}
		}

		private static SlimeController ControllerFor(int playerId)
		{
			if (controllers.TryGetValue(playerId, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			SlimeController[] array = Object.FindObjectsOfType<SlimeController>();
			foreach (SlimeController val in array)
			{
				if (val.GetPlayerId() == playerId)
				{
					controllers[playerId] = val;
					return val;
				}
			}
			return null;
		}

		public static void ClearAll()
		{
			deployed.Clear();
			controllers.Clear();
		}
	}
	internal static class BubbleSound
	{
		public const string Throw = "throwSmallItem";

		public const string Bounce = "rockBounce";

		public const string Pop = "magnetCancel";

		public const float PopPitch = 1.6f;

		public static void Play(string name)
		{
			AudioManager val = AudioManager.Get();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (name == "magnetCancel")
			{
				AudioSource val2 = val.Play(name, 0f);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.pitch *= 1.6f;
				}
			}
			else
			{
				val.Play(name);
			}
		}
	}
	public static class BubbleState
	{
		private class Bubble
		{
			public GameObject Visual;

			public SpriteRenderer Renderer;

			public int OwnerId;

			public long Key;

			public Vec2 Position;

			public Vec2 Direction;

			public int Contacts;

			public int TicksAlive;

			public float SpinAngle;

			public Fix Scale;
		}

		private static readonly List<Bubble> bubbles = new List<Bubble>();

		private static bool warnedAboutMass;

		private static readonly Dictionary<int, SlimeController> controllers = new Dictionary<int, SlimeController>();

		public static int Count => bubbles.Count;

		public static bool HasBubble(long key)
		{
			foreach (Bubble bubble in bubbles)
			{
				if (bubble.Key == key)
				{
					return true;
				}
			}
			return false;
		}

		public static void Throw(int playerId, long key, Vec2 origin, Vec2 aim)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_006d: 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_0091: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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)
			if (Vec2.SqrMagnitude(aim) <= Fix.Zero)
			{
				aim = Vec2.up;
			}
			aim = Vec2.Normalized(aim);
			Fix val = ScaleOf(playerId);
			Bubble bubble = new Bubble
			{
				OwnerId = playerId,
				Key = key,
				Scale = val,
				Position = origin + aim * (BubbleAbility.Radius * val * (Fix)2L),
				Direction = aim,
				Contacts = 0,
				TicksAlive = 0
			};
			bubble.Visual = new GameObject("BubbleGumBall");
			bubble.Renderer = bubble.Visual.AddComponent<SpriteRenderer>();
			bubble.Renderer.sprite = BubbleVisuals.BubbleSprite();
			((Renderer)bubble.Renderer).sortingOrder = 900;
			bubble.Visual.transform.localScale = new Vector3((float)val, (float)val, 1f);
			bubbles.Add(bubble);
			BubbleSound.Play("throwSmallItem");
			Plugin.Log.LogInfo((object)$"Bubble Gum: player {playerId} threw a bubble.");
		}

		private static Fix ScaleOf(int playerId)
		{
			//IL_001e: 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)
			PlayerHandler val = PlayerHandler.Get();
			Player val2 = ((val == null) ? null : val.GetPlayer(playerId));
			if (val2 != null)
			{
				return val2.Scale;
			}
			return Fix.One;
		}

		public static void Tick()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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)
			if (bubbles.Count == 0)
			{
				return;
			}
			Fix fixedTimeStep = GameTime.FixedTimeStep;
			for (int num = bubbles.Count - 1; num >= 0; num--)
			{
				Bubble bubble = bubbles[num];
				if (!GameTime.IsTimeStoppedFor(bubble.OwnerId))
				{
					bubble.TicksAlive++;
					if (bubble.TicksAlive > 900)
					{
						Pop(num, "it ran out of time");
					}
					else if (BlackHolePull(bubble, fixedTimeStep))
					{
						Pop(num, "a black hole swallowed it");
					}
					else if (!Advance(bubble, fixedTimeStep))
					{
						Pop(num, "it made its last contact");
					}
					else if (OutOfPlay(bubble.Position))
					{
						Pop(num, "it left the map");
					}
					else
					{
						BubbleVisuals.Draw(bubble.Visual, bubble.Position, ref bubble.SpinAngle);
					}
				}
			}
		}

		private static bool BlackHolePull(Bubble bubble, Fix dt)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_005a: 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_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_0072: 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_007f: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00be: 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_00d0: 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_00d4: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			BlackHole[] array = Object.FindObjectsOfType<BlackHole>();
			foreach (BlackHole val in array)
			{
				if ((Object)(object)val == (Object)null || ((MonoUpdatable)val).IsDestroyed || (Object)(object)val.dCircle == (Object)null)
				{
					continue;
				}
				Vec2 val2 = val.dCircle.position - bubble.Position;
				Fix val3 = Vec2.SqrMagnitude(val2);
				if (val3 <= Fix.Zero)
				{
					continue;
				}
				Fix val4 = Fix.Sqrt(val3);
				if (val4 <= val.dCircle.radius * BubbleAbility.BlackHoleSwallowRadius)
				{
					return true;
				}
				if (!(val4 >= val.dCircle.radius * val.influenceRadiusMultiplier))
				{
					Fix val5 = val3 * val4;
					if (!(val5 <= Fix.Zero))
					{
						Fix val6 = MassOf(val);
						Vec2 val7 = val2 * (val.G * val6 * BubbleAbility.BlackHolePull) / val5;
						bubble.Direction = Vec2.NormalizedSafe(bubble.Direction + val7 * dt);
					}
				}
			}
			return false;
		}

		private static Fix MassOf(BlackHole hole)
		{
			//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_0048: 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)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return Traverse.Create((object)hole).Field("mass").GetValue<Fix>();
			}
			catch (Exception ex)
			{
				if (!warnedAboutMass)
				{
					warnedAboutMass = true;
					Plugin.Log.LogWarning((object)("Bubble Gum: could not read a black hole's mass, so its pull on the bubble uses a fixed strength: " + ex.Message));
				}
				return BubbleAbility.FallbackBlackHoleMass;
			}
		}

		private static bool Advance(Bubble bubble, Fix dt)
		{
			//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_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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)
			//IL_0041: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			Fix val = BubbleAbility.Speed * dt;
			for (int i = 0; i < 6; i++)
			{
				if (!(val > Fix.Zero))
				{
					break;
				}
				if (!FindWall(bubble, val, out var hitPoint, out var normal, out var travelled))
				{
					bubble.Position += bubble.Direction * val;
					break;
				}
				bubble.Position = hitPoint + normal * (BubbleAbility.BounceClearance * bubble.Scale);
				val -= travelled;
				if (!Contact(bubble, normal))
				{
					return false;
				}
			}
			if (!TouchObjects(bubble))
			{
				return false;
			}
			return TouchPlayers(bubble);
		}

		private static bool FindWall(Bubble bubble, Fix distance, out Vec2 hitPoint, out Vec2 normal, out Fix travelled)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_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_001f: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_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_0087: 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)
			//IL_00a4: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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)
			hitPoint = bubble.Position;
			normal = -bubble.Direction;
			travelled = distance;
			DetPhysics val = DetPhysics.Get();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Fix val2 = distance + BubbleAbility.Radius * bubble.Scale;
			RaycastInformation val3 = val.RaycastToClosest(bubble.Position, bubble.Direction, val2, LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { "wall" })));
			if (!RaycastInformation.op_Implicit(val3) || val3.nearDist > val2)
			{
				return false;
			}
			travelled = Fix.Max(Fix.Zero, val3.nearDist - BubbleAbility.Radius * bubble.Scale);
			hitPoint = bubble.Position + bubble.Direction * travelled;
			normal = SurfaceNormal(val3, hitPoint, bubble.Position);
			if (Vec2.Dot(bubble.Direction, normal) >= Fix.Zero)
			{
				return false;
			}
			return true;
		}

		private static Vec2 SurfaceNormal(RaycastInformation hit, Vec2 hitPoint, Vec2 from)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: 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_0073: 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_0051: 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_005e: 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_006b: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_004a: 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)
			FixTransform fixTrans = hit.pp.fixTrans;
			if ((Object)(object)fixTrans != (Object)null && !fixTrans.IsDestroyed)
			{
				StickyRoundedRectangle component = ((Component)fixTrans).GetComponent<StickyRoundedRectangle>();
				if ((Object)(object)component != (Object)null && !((MonoUpdatable)component).IsDestroyed)
				{
					Vec2 val = component.currentNormal(hitPoint);
					if (val != Vec2.zero)
					{
						return Vec2.NormalizedSafe(val);
					}
				}
				Vec2 val2 = hitPoint - fixTrans.position;
				if (val2 != Vec2.zero)
				{
					return Vec2.NormalizedSafe(val2);
				}
			}
			return Vec2.NormalizedSafe(from - hitPoint);
		}

		private static bool Contact(Bubble bubble, Vec2 normal)
		{
			//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_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_0028: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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)
			//IL_0045: 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)
			bubble.Contacts++;
			if (bubble.Contacts >= 4)
			{
				return false;
			}
			Fix val = Vec2.Dot(bubble.Direction, normal);
			bubble.Direction = Vec2.NormalizedSafe(bubble.Direction - normal * (val * (Fix)2L));
			BubbleSound.Play("rockBounce");
			return true;
		}

		private static bool TouchObjects(Bubble bubble)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			Fix val = BubbleAbility.Radius * bubble.Scale + BubbleAbility.ObjectReach;
			Fix val2 = val * val;
			Arrow[] array = Object.FindObjectsOfType<Arrow>();
			for (int i = 0; i < array.Length; i++)
			{
				if (PositionOf((Component)(object)array[i], out var position) && !(Vec2.SqrMagnitude(position - bubble.Position) > val2))
				{
					Plugin.Log.LogInfo((object)($"Bubble Gum: player {bubble.OwnerId}'s bubble was popped by an " + "arrow."));
					return false;
				}
			}
			GrenadeExplode[] array2 = Object.FindObjectsOfType<GrenadeExplode>();
			foreach (GrenadeExplode thing in array2)
			{
				if (!BounceOff(bubble, (Component)(object)thing, val2, "a grenade"))
				{
					return false;
				}
			}
			Mine[] array3 = Object.FindObjectsOfType<Mine>();
			foreach (Mine thing2 in array3)
			{
				if (!BounceOff(bubble, (Component)(object)thing2, val2, "a mine"))
				{
					return false;
				}
			}
			return true;
		}

		private static bool BounceOff(Bubble bubble, Component thing, Fix reachSquared, string what)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//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_0019: 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_0029: 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)
			//IL_002f: 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_0031: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (!PositionOf(thing, out var position))
			{
				return true;
			}
			Vec2 val = bubble.Position - position;
			if (Vec2.SqrMagnitude(val) > reachSquared)
			{
				return true;
			}
			Vec2 val2 = Vec2.NormalizedSafe(val);
			if (val2 == Vec2.zero || Vec2.Dot(bubble.Direction, val2) >= Fix.Zero)
			{
				return true;
			}
			Plugin.Log.LogInfo((object)$"Bubble Gum: player {bubble.OwnerId}'s bubble bounced off {what}.");
			return Contact(bubble, val2);
		}

		private static bool PositionOf(Component thing, out Vec2 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			position = Vec2.zero;
			if ((Object)(object)thing == (Object)null)
			{
				return false;
			}
			FixTransform component = thing.GetComponent<FixTransform>();
			if ((Object)(object)component == (Object)null || component.IsDestroyed)
			{
				return false;
			}
			position = component.position;
			return true;
		}

		private static bool TouchPlayers(Bubble bubble)
		{
			//IL_0011: 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_001c: 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)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: 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)
			PlayerHandler val = PlayerHandler.Get();
			if (val == null)
			{
				return true;
			}
			Fix val2 = BubbleAbility.Radius * bubble.Scale + (Fix)0.7;
			Fix reachSquared = val2 * val2;
			foreach (Player item in val.PlayerList())
			{
				if (item == null || !item.IsAlive || (item.Id == bubble.OwnerId && bubble.TicksAlive < 45))
				{
					continue;
				}
				Vec2 centre = bubble.Position;
				int bodiesSeen;
				int num = PlayerBodies.KillWhere(item.Id, bubble.OwnerId, (CauseOfDeath)1, delegate(Vec2 position)
				{
					//IL_0000: Unknown result type (might be due to invalid IL or missing references)
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_000c: Unknown result type (might be due to invalid IL or missing references)
					//IL_000d: 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)
					Vec2 val6 = position - centre;
					return Vec2.Dot(val6, val6) <= reachSquared;
				}, out bodiesSeen);
				if (num > 0)
				{
					Plugin.Log.LogInfo((object)($"Bubble Gum: player {bubble.OwnerId}'s bubble caught player " + $"{item.Id} ({num} of {bodiesSeen} bodies)."));
				}
				else
				{
					if (bodiesSeen == 0)
					{
						PlayerBodies.WarnIfBlind(bodiesSeen, "Bubble Gum");
						Vec2 val3 = item.Position - bubble.Position;
						if (Vec2.Dot(val3, val3) <= reachSquared)
						{
							PlayerCollision val4 = ActiveCollisionFor(item.Id);
							if ((Object)(object)val4 != (Object)null)
							{
								val4.killPlayer(bubble.OwnerId, true, false, (CauseOfDeath)1);
								num = 1;
							}
						}
					}
					if (num == 0)
					{
						continue;
					}
				}
				Vec2 val5 = bubble.Position - item.Position;
				Vec2 normal = ((val5 == Vec2.zero) ? (-bubble.Direction) : Vec2.NormalizedSafe(val5));
				if (!Contact(bubble, normal))
				{
					return false;
				}
				break;
			}
			return true;
		}

		private static bool OutOfPlay(Vec2 position)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0053: 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)
			if (Constants.isSpaceLevel)
			{
				if (position.y < SceneBounds.Camera_YMin)
				{
					return true;
				}
			}
			else if (position.y < SceneBounds.WaterHeight)
			{
				return true;
			}
			if (!(position.y > SceneBounds.BlastZone_YMax) && !(position.x < SceneBounds.BlastZone_XMin))
			{
				return position.x > SceneBounds.BlastZone_XMax;
			}
			return true;
		}

		private static void Pop(int index, string reason)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Bubble bubble = bubbles[index];
			BubbleVisuals.SpawnPop(bubble.Position);
			BubbleSound.Play("magnetCancel");
			Plugin.Log.LogInfo((object)($"Bubble Gum: player {bubble.OwnerId}'s bubble popped because {reason} " + $"({bubble.Contacts} contacts)."));
			Remove(index);
		}

		private static void Remove(int index)
		{
			Bubble bubble = bubbles[index];
			if ((Object)(object)bubble.Visual != (Object)null)
			{
				Object.Destroy((Object)(object)bubble.Visual);
			}
			bubbles.RemoveAt(index);
			BubbleRegistry.BubbleGone(bubble.Key);
		}

		private static PlayerCollision ActiveCollisionFor(int playerId)
		{
			if (!controllers.TryGetValue(playerId, out var value) || (Object)(object)value == (Object)null)
			{
				value = null;
				SlimeController[] array = Object.FindObjectsOfType<SlimeController>();
				foreach (SlimeController val in array)
				{
					if (val.GetPlayerId() == playerId)
					{
						value = val;
						controllers[playerId] = val;
						break;
					}
				}
			}
			if (!((Object)(object)value == (Object)null))
			{
				return value.GetActivePlayerCollision();
			}
			return null;
		}

		public static void ClearAll()
		{
			for (int num = bubbles.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)bubbles[num].Visual != (Object)null)
				{
					Object.Destroy((Object)(object)bubbles[num].Visual);
				}
				bubbles.RemoveAt(num);
			}
			controllers.Clear();
		}
	}
	public static class BubbleVisuals
	{
		private static Sprite bubble;

		private static bool loadAttempted;

		public static Sprite BubbleSprite()
		{
			if (!loadAttempted)
			{
				loadAttempted = true;
				bubble = BubbleAbility.LoadBubble();
				if ((Object)(object)bubble == (Object)null)
				{
					Plugin.Log.LogError((object)"Bubble Gum: the ball art failed to load, so bubbles will be invisible. They still bounce and still kill.");
				}
			}
			return bubble;
		}

		public static void Draw(GameObject visual, Vec2 position, ref float spinAngle)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//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_003c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)visual == (Object)null))
			{
				visual.transform.position = Vector2.op_Implicit((Vector2)position);
				spinAngle += 6f;
				visual.transform.rotation = Quaternion.Euler(0f, 0f, spinAngle);
			}
		}

		public static void SpawnPop(Vec2 position)
		{
			//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_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_0030: 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)
			Sprite val = BubbleSprite();
			if (!((Object)(object)val == (Object)null))
			{
				GameObject val2 = new GameObject("BubbleGumPop");
				val2.transform.position = Vector2.op_Implicit((Vector2)position);
				SpriteRenderer obj = val2.AddComponent<SpriteRenderer>();
				obj.sprite = val;
				obj.color = BubbleAbility.GumColour;
				((Renderer)obj).sortingOrder = 901;
				val2.AddComponent<BubblePop>();
			}
		}
	}
	internal class BubblePop : MonoBehaviour
	{
		private const float Life = 0.22f;

		private float age;

		private void Update()
		{
			//IL_0042: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			age += Time.deltaTime;
			float num = Mathf.Clamp01(age / 0.22f);
			float num2 = Mathf.Lerp(1f, 2.1f, num);
			((Component)this).transform.localScale = new Vector3(num2, num2, 1f);
			SpriteRenderer component = ((Component)this).GetComponent<SpriteRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				Color color = component.color;
				color.a = 1f - num;
				component.color = color;
			}
			if (num >= 1f)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
	internal static class PlayerBodies
	{
		private static bool warnedEmpty;

		private static readonly HashSet<int> alreadyKilled = new HashSet<int>();

		public static void ForgetAll()
		{
			alreadyKilled.Clear();
		}

		public static bool IsProtected(int playerId)
		{
			PlayerHandler val = PlayerHandler.Get();
			Player val2 = ((val == null) ? null : val.GetPlayer(playerId));
			if (val2 != null && val2.InPlatformTransform)
			{
				return true;
			}
			ControlPlatform[] array = Object.FindObjectsOfType<ControlPlatform>();
			foreach (ControlPlatform val3 in array)
			{
				if (!((Object)(object)val3 == (Object)null) && ((Behaviour)val3).isActiveAndEnabled)
				{
					IPlayerIdHolder component = ((Component)val3).GetComponent<IPlayerIdHolder>();
					if (component != null && component.GetPlayerId() == playerId)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static int KillWhere(int victimId, int killerId, CauseOfDeath causeOfDeath, Func<Vec2, bool> isInside, out int bodiesSeen, bool respectProtection = true)
		{
			//IL_0075: 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)
			bodiesSeen = 0;
			int num = 0;
			if (respectProtection && IsProtected(victimId))
			{
				return 0;
			}
			PlayerCollision[] array = Object.FindObjectsOfType<PlayerCollision>();
			foreach (PlayerCollision val in array)
			{
				if ((Object)(object)val == (Object)null || ((MonoUpdatable)val).IsDestroyed || !((Component)val).gameObject.activeInHierarchy || val.GetPlayerId() != victimId)
				{
					continue;
				}
				FixTransform component = ((Component)val).GetComponent<FixTransform>();
				if (!((Object)(object)component == (Object)null) && !component.IsDestroyed)
				{
					bodiesSeen++;
					if (isInside(component.position) && !alreadyKilled.Contains(((Object)val).GetInstanceID()) && val.killPlayer(killerId, true, !respectProtection, causeOfDeath))
					{
						alreadyKilled.Add(((Object)val).GetInstanceID());
						num++;
					}
				}
			}
			return num;
		}

		public static int KillAll(int victimId, int killerId, CauseOfDeath causeOfDeath, out int bodiesSeen, bool respectProtection = true)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return KillWhere(victimId, killerId, causeOfDeath, (Vec2 position) => true, out bodiesSeen, respectProtection);
		}

		public static void WarnIfBlind(int bodiesSeen, string what)
		{
			if (bodiesSeen <= 0 && !warnedEmpty)
			{
				warnedEmpty = true;
				Plugin.Log.LogWarning((object)(what + ": no live PlayerCollision was found for the target, so nothing can be killed. Every kill in this mod goes through that lookup, so this is not a near miss -- the scan itself is blind and the ability will appear to do nothing. Falling back to the old single-body lookup for this hit."));
			}
		}
	}
	[BepInPlugin("com.maha.boplbattle.bubblegum", "Bubble Gum", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.maha.boplbattle.bubblegum";

		public const string PluginName = "Bubble Gum";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"Bubble Gum: loading...");
			new Harmony("com.maha.boplbattle.bubblegum").PatchAll();
			Log.LogInfo((object)($"Bubble Gum: loaded (speed {(float)BubbleAbility.Speed:0.#}, pops on contact " + $"{4}, reload {3.9f}s)."));
		}
	}
}