Decompiled source of BubbleBlasterRecode v2.8.6

Mods/BubbleBlasterRecode.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BoneLib;
using BubbleBlasterRecode;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.AI;
using Il2CppSLZ.Marrow.Combat;
using Il2CppSLZ.Marrow.Data;
using Il2CppSLZ.Marrow.Interaction;
using Il2CppSLZ.Marrow.Pool;
using Il2CppSLZ.Marrow.PuppetMasta;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(BubbleBlasterMod), "BubbleBlasterRecode", "2.8.5", "Shippy", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]
[assembly: AssemblyCompany("BubbleBlasterRecode")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0")]
[assembly: AssemblyProduct("BubbleBlasterRecode")]
[assembly: AssemblyTitle("BubbleBlasterRecode")]
[assembly: AssemblyVersion("2.0.0.0")]
[module: RefSafetyRules(11)]
namespace BubbleBlasterRecode;

public class BubbleController
{
	private enum Phase
	{
		Flight,
		Holding,
		CamoHover,
		DecoyParked,
		FloatPark,
		Popped
	}

	private readonly BubbleTypeInfo info;

	private readonly bool straight;

	private bool straightPhaseOver;

	private readonly Rigidbody rb;

	private readonly MembraneVisual visual;

	private readonly RadiusSpring radius;

	private readonly SphereCollider solidCollider;

	private readonly BoxCollider camoFloor;

	private readonly AudioClip popClip;

	private readonly ParticleSystem popParticles;

	private readonly float wobSeed;

	private readonly float bornAt;

	private readonly Vector3 spawnPos;

	private float hp;

	private Vector3 vel;

	private Vector3 launchDir;

	private Vector3 launchVel;

	private Phase phase;

	private float hoverY;

	private bool hovering;

	private Vector3 hoverXZ;

	private LivingTarget captive;

	private float captureAt;

	private int struggles;

	private float nextNpcStruggle;

	private float healBank;

	private float nextHealChunk;

	private float healedTotal;

	private float suffBank;

	private float reviveAt;

	private Vector3 lastWallPoint;

	private Vector3 lastWallNormal = Vector3.up;

	private bool haveWallPoint;

	private GameObject decoyBody;

	private bool decoyLanded;

	private float decoyFloorY = float.MinValue;

	private float lastShotAt;

	private float nextShotScan;

	private bool playerSolid;

	private float nextPlayerGate;

	private float nextReassert;

	private readonly bool remote;

	private Vector3 remoteLastPos;

	private float remoteSettledSecs;

	private bool remoteBloomed;

	private bool remoteParked;

	private readonly RigManager casterRig;

	private readonly List<RigManager> cloakedRigs = new List<RigManager>();

	private float nextCloak;

	private float ascendScale = 1f;

	private static readonly string[] StripTypeNames = new string[5] { "UltEvents.UltEventHolder", "UltEvents.DelayedUltEventHolder", "UltEvents.LifeCycleEvents", "UltEvents.UpdateEvents", "UltEvents.TriggerEvents3D" };

	private float hoverGroundY = float.MinValue;

	public GameObject Root { get; private set; }

	public bool Dead
	{
		get
		{
			if (!((Object)(object)Root == (Object)null))
			{
				return phase == Phase.Popped;
			}
			return true;
		}
	}

	public bool Remote => remote;

	private float Now => Time.time;

	private float SimT => Now - bornAt;

	private bool EffStraight
	{
		get
		{
			if (straight)
			{
				return !straightPhaseOver;
			}
			return false;
		}
	}

	public float Age => Time.time - bornAt;

	public BubbleController(GameObject root, BubbleTypeInfo typeInfo, bool straightMode, GunManager gun, bool remoteMode = false)
	{
		//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_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_044a: Unknown result type (might be due to invalid IL or missing references)
		//IL_044f: 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_0460: 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_046c: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04da: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0501: Unknown result type (might be due to invalid IL or missing references)
		//IL_050b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0510: Unknown result type (might be due to invalid IL or missing references)
		//IL_0517: Unknown result type (might be due to invalid IL or missing references)
		//IL_051c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0482: Unknown result type (might be due to invalid IL or missing references)
		//IL_0487: Unknown result type (might be due to invalid IL or missing references)
		//IL_048f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0495: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_056e: Unknown result type (might be due to invalid IL or missing references)
		//IL_057f: Unknown result type (might be due to invalid IL or missing references)
		//IL_058f: Unknown result type (might be due to invalid IL or missing references)
		Root = root;
		info = typeInfo;
		straight = straightMode;
		remote = remoteMode;
		bornAt = Time.time;
		hp = info.Hp;
		wobSeed = Random.value * 20f;
		GameObject val = gun?.Root;
		casterRig = (remote ? EntityUtil.NearestRig(root.transform.position, 10f) : null);
		rb = root.GetComponent<Rigidbody>();
		StripPalletLogic(root);
		if ((Object)(object)val != (Object)null)
		{
			EntityUtil.IgnoreCollisionsWith(root, val);
		}
		GameObject val2 = EntityUtil.PlayerRoot();
		if ((Object)(object)val2 != (Object)null)
		{
			EntityUtil.IgnoreCollisionsWith(root, val2);
		}
		Renderer filmRenderer = null;
		Transform transform = root.transform;
		foreach (Renderer componentsInChild in root.GetComponentsInChildren<Renderer>(true))
		{
			Material sharedMaterial = componentsInChild.sharedMaterial;
			if ((Object)(object)sharedMaterial != (Object)null && ((Object)sharedMaterial).name.Contains("Bubble"))
			{
				filmRenderer = componentsInChild;
				transform = ((Component)componentsInChild).transform;
				((Component)componentsInChild).gameObject.SetActive(true);
				break;
			}
		}
		popParticles = root.GetComponentInChildren<ParticleSystem>(true);
		Material tintSource = null;
		if ((Object)(object)popParticles != (Object)null)
		{
			if (popParticles.isPlaying)
			{
				popParticles.Stop();
			}
			ParticleSystemRenderer component = ((Component)popParticles).GetComponent<ParticleSystemRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				tintSource = ((Renderer)component).sharedMaterial;
			}
		}
		AudioSource componentInChildren = root.GetComponentInChildren<AudioSource>(true);
		popClip = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.clip : null);
		radius = new RadiusSpring(Tuning.BaseRadius * 0.55f, 0.18f, 4.5f);
		radius.Target = (straight ? Tuning.BaseRadius : Tuning.CastRadius);
		visual = new MembraneVisual(root, transform, filmRenderer, radius.Radius, tintSource);
		visual.ApplyType(info);
		visual.SetFade(1f);
		MembraneVisual.TintEffects(root, info.ShellColor);
		Transform val3 = root.transform.Find("BubbleFilm");
		if (info.Solid)
		{
			GameObject val4 = (GameObject)(((Object)(object)val3 != (Object)null) ? ((object)((Component)val3).gameObject) : ((object)new GameObject("BubbleFilm")));
			val4.transform.SetParent(root.transform, false);
			val4.transform.localPosition = Vector3.zero;
			val4.SetActive(true);
			solidCollider = val4.GetComponent<SphereCollider>();
			if ((Object)(object)solidCollider == (Object)null)
			{
				solidCollider = val4.AddComponent<SphereCollider>();
			}
			solidCollider.radius = radius.Radius * 0.995f;
			((Collider)solidCollider).enabled = false;
			if ((Object)(object)val != (Object)null)
			{
				EntityUtil.IgnoreCollisionsWith(val4, val);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				EntityUtil.IgnoreCollisionsWith(val4, val2);
			}
		}
		else if ((Object)(object)val3 != (Object)null)
		{
			((Component)val3).gameObject.SetActive(false);
		}
		Transform val5 = root.transform.Find("CamoFloor");
		if (info.Type == BubbleType.Camo)
		{
			GameObject val6 = (GameObject)(((Object)(object)val5 != (Object)null) ? ((object)((Component)val5).gameObject) : ((object)new GameObject("CamoFloor")));
			val6.transform.SetParent(root.transform, false);
			val6.transform.localPosition = Vector3.zero;
			val6.SetActive(true);
			camoFloor = val6.GetComponent<BoxCollider>();
			if ((Object)(object)camoFloor == (Object)null)
			{
				camoFloor = val6.AddComponent<BoxCollider>();
			}
			((Collider)camoFloor).enabled = false;
			if ((Object)(object)val != (Object)null)
			{
				EntityUtil.IgnoreCollisionsWith(val6, val);
			}
		}
		else if ((Object)(object)val5 != (Object)null)
		{
			((Component)val5).gameObject.SetActive(false);
		}
		if (remote)
		{
			launchDir = root.transform.forward;
			spawnPos = root.transform.position;
			remoteLastPos = spawnPos;
			return;
		}
		if (gun != null && !gun.Dead)
		{
			launchDir = gun.MuzzleForward;
			spawnPos = gun.MuzzlePos + launchDir * (Tuning.BaseRadius * 0.5f + 0.22f);
		}
		else
		{
			launchDir = root.transform.forward;
			spawnPos = root.transform.position + launchDir * (Tuning.BaseRadius * 0.5f + 0.22f);
		}
		launchVel = launchDir * Tuning.StraightSpeed;
		vel = launchVel;
		if ((Object)(object)rb != (Object)null)
		{
			rb.useGravity = false;
			rb.isKinematic = false;
			rb.drag = 0f;
			rb.angularDrag = 1f;
			rb.position = spawnPos;
			rb.velocity = launchVel;
			rb.angularVelocity = Vector3.zero;
			rb.maxDepenetrationVelocity = 1.5f;
		}
	}

	public void AbandonSilently()
	{
		if (phase != Phase.Popped)
		{
			phase = Phase.Popped;
			if (captive != null)
			{
				EntityUtil.SetCaptured(captive, captured: false);
				captive = null;
			}
			if ((Object)(object)decoyBody != (Object)null)
			{
				Object.Destroy((Object)(object)decoyBody);
				decoyBody = null;
			}
			EntityUtil.UncloakAll(cloakedRigs);
			visual.SetFade(1f);
			Root = null;
		}
	}

	internal static void StripPalletLogic(GameObject root)
	{
		foreach (Component componentsInChild in root.GetComponentsInChildren<Component>(true))
		{
			if ((Object)(object)componentsInChild == (Object)null)
			{
				continue;
			}
			string fullName;
			try
			{
				fullName = ((Object)componentsInChild).GetIl2CppType().FullName;
			}
			catch
			{
				continue;
			}
			try
			{
				string[] stripTypeNames = StripTypeNames;
				foreach (string text in stripTypeNames)
				{
					if (fullName == text)
					{
						Object.DestroyImmediate((Object)(object)componentsInChild);
						break;
					}
				}
				if (fullName == "SLZ.Marrow.Warehouse.CrateSpawner" && (Object)(object)componentsInChild != (Object)null && (Object)(object)componentsInChild.gameObject != (Object)(object)root)
				{
					Object.DestroyImmediate((Object)(object)componentsInChild.gameObject);
				}
			}
			catch
			{
			}
		}
	}

	public void Update(float dt)
	{
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Root == (Object)null || !Root.activeInHierarchy)
		{
			if (phase != Phase.Popped)
			{
				phase = Phase.Popped;
				if (captive != null)
				{
					EntityUtil.SetCaptured(captive, captured: false);
					captive = null;
				}
				if ((Object)(object)decoyBody != (Object)null)
				{
					Object.Destroy((Object)(object)decoyBody);
					decoyBody = null;
				}
				EntityUtil.UncloakAll(cloakedRigs);
			}
			Root = null;
			return;
		}
		radius.Step(dt);
		visual.SetRadius(radius.Radius);
		float speedFrac = ((phase == Phase.Flight) ? Mathf.Clamp01(((Vector3)(ref vel)).magnitude / 19.5881f) : 0f);
		float minSquish = ((phase == Phase.Holding) ? 0.965f : 0.55f);
		visual.Update(dt, speedFrac, captive != null, info.MembraneStrength, minSquish);
		if ((Object)(object)solidCollider != (Object)null)
		{
			solidCollider.radius = visual.TintSurfaceRadius * 0.9f;
			((Collider)solidCollider).enabled = phase == Phase.Holding || phase == Phase.FloatPark || (remote && remoteParked);
			if (Now >= nextPlayerGate)
			{
				nextPlayerGate = Now + 0.1f;
				UpdatePlayerGate(((Collider)solidCollider).enabled);
			}
		}
		if ((Object)(object)camoFloor != (Object)null)
		{
			float num = radius.Radius * 0.88f;
			float num2 = radius.Radius * 0.45f;
			((Component)camoFloor).transform.localPosition = new Vector3(0f, 0f - num, 0f);
			camoFloor.size = new Vector3(num2 * 2f, 0.1f, num2 * 2f);
			((Collider)camoFloor).enabled = phase == Phase.CamoHover || (remote && remoteParked);
		}
	}

	private void UpdatePlayerGate(bool solidNow)
	{
		//IL_007d: 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)
		bool flag = solidNow && (captive == null || !captive.IsPlayer) && ((info.Type != BubbleType.Healing || captive != null || !Tuning.CapturePlayer || !EntityUtil.PlayerIsHurt()) ? true : false);
		if (flag != playerSolid && (!flag || !(EntityUtil.PlayerHeadDistance(((Object)(object)rb != (Object)null) ? rb.position : Root.transform.position) < radius.Radius + 0.35f)))
		{
			playerSolid = flag;
			EntityUtil.IgnoreCollisionsWith(((Component)solidCollider).gameObject, EntityUtil.PlayerRoot(), !flag);
		}
	}

	public void FixedUpdate(float dt)
	{
		if (Dead)
		{
			return;
		}
		if (remote)
		{
			StepRemote(dt);
			return;
		}
		DetectShots();
		switch (phase)
		{
		case Phase.Flight:
			StepFlight(dt);
			break;
		case Phase.Holding:
			StepHolding(dt);
			break;
		case Phase.CamoHover:
			StepCamoHover(dt);
			break;
		case Phase.DecoyParked:
			StepDecoyParked(dt);
			break;
		case Phase.FloatPark:
			StepFloatPark(dt);
			break;
		}
	}

	private void StepRemote(float dt)
	{
		//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_0022: 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_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_021a: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: 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_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		if (phase == Phase.Holding)
		{
			StepHolding(dt);
			return;
		}
		Vector3 position = Root.transform.position;
		Vector3 val = position - remoteLastPos;
		float num = ((Vector3)(ref val)).magnitude / Mathf.Max(dt, 0.0001f);
		remoteLastPos = position;
		if (num < 1f)
		{
			remoteSettledSecs += dt;
		}
		else
		{
			remoteSettledSecs = 0f;
			remoteParked = false;
		}
		if (!remoteBloomed && (SimT >= 3.5f || (remoteSettledSecs > 0.35f && SimT > 0.4f)))
		{
			remoteBloomed = true;
			if (info.Type != BubbleType.Decoy)
			{
				radius.Target = Tuning.CastRadius;
			}
			visual.Soap.KickRandom(1.1f);
		}
		if (!remoteParked && remoteSettledSecs > 0.8f)
		{
			remoteParked = true;
			if (info.Type == BubbleType.Decoy)
			{
				RemoteDecoyPark(position);
			}
		}
		switch (info.Type)
		{
		case BubbleType.Camo:
			visual.SetFade(ProximityFade(position, 0f));
			if (Now >= nextCloak)
			{
				nextCloak = Now + 0.25f;
				EntityUtil.CloakRigsInside(position, radius.Radius, cloakedRigs);
			}
			if (EntityUtil.PlayerHeadInside(position, radius.Radius + 0.28f))
			{
				EntityUtil.CloakPlayerTick(position, Tuning.DetectRange * 2f);
			}
			break;
		case BubbleType.Decoy:
			visual.SetFade(ProximityFade(position, ((Object)(object)decoyBody != (Object)null) ? 0f : 0.35f));
			EntityUtil.AttractAggro(Root, position, Tuning.DecoyBurstRange * 1.5f);
			break;
		case BubbleType.Healing:
			if (Now >= nextShotScan)
			{
				nextShotScan = Now + 0.1f;
				LivingTarget livingTarget = EntityUtil.PlayerDeepInside(position, radius.Radius, spawnPos);
				if (livingTarget != null)
				{
					Seal(livingTarget);
					break;
				}
			}
			OuterTouchHeal(position, dt);
			break;
		}
	}

	private void RemoteDecoyPark(Vector3 pos)
	{
		//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_0025: 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_0045: Unknown result type (might be due to invalid IL or missing references)
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(pos, Vector3.down, ref val, 6f + radius.Radius, -5, (QueryTriggerInteraction)1) && ((RaycastHit)(ref val)).normal.y > 0.6f)
		{
			decoyBody = EntityUtil.SpawnHologramOf(casterRig, ((RaycastHit)(ref val)).point, launchDir, out var height);
			if ((Object)(object)decoyBody != (Object)null)
			{
				radius.Target = DecoyFit(height);
				return;
			}
		}
		radius.Target = DecoyFit(EntityUtil.AvatarHeight(casterRig));
	}

	private void ReleaseOrPop()
	{
		if (!remote)
		{
			Pop();
			return;
		}
		if (captive != null)
		{
			EntityUtil.SetCaptured(captive, captured: false);
			captive = null;
		}
		phase = Phase.Flight;
	}

	private bool ForeignHit(Transform hitTf)
	{
		if ((Object)(object)hitTf == (Object)null)
		{
			return false;
		}
		Transform val = hitTf;
		while ((Object)(object)val != (Object)null)
		{
			if ((Object)(object)((Component)val).gameObject == (Object)(object)Root)
			{
				return false;
			}
			if (((Object)val).name.Contains("BubbleProjectile"))
			{
				return false;
			}
			val = val.parent;
		}
		if (EntityUtil.IsPlayerPart(hitTf))
		{
			return false;
		}
		if (EntityUtil.IsGunPart(hitTf))
		{
			return false;
		}
		return true;
	}

	private void LimitFlightInflation(Vector3 pos, bool groundKnown, float groundY)
	{
		//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_003b: 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_006e: Unknown result type (might be due to invalid IL or missing references)
		if (!EffStraight)
		{
			float num = Tuning.CastRadius;
			Transform val = EntityUtil.PlayerHead();
			if ((Object)(object)val != (Object)null)
			{
				num = Mathf.Min(num, Vector3.Distance(val.position, pos) - 0.45f);
			}
			if (groundKnown)
			{
				num = Mathf.Min(num, Mathf.Max(pos.y - groundY, Tuning.BaseRadius * 0.6f));
			}
			if (haveWallPoint)
			{
				float num2 = Vector3.Dot(pos - lastWallPoint, lastWallNormal);
				num = Mathf.Min(num, Mathf.Max(num2, Tuning.BaseRadius * 0.6f));
			}
			radius.Target = Mathf.Clamp(num, Tuning.BaseRadius * 0.6f, Tuning.CastRadius);
		}
	}

	private void StepFlight(float dt)
	{
		//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_0053: 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_003a: 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_0096: 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_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: 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_00dd: 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_00e8: 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_00fb: 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_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: 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_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: 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_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_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0435: 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)
		//IL_0440: Unknown result type (might be due to invalid IL or missing references)
		//IL_0445: Unknown result type (might be due to invalid IL or missing references)
		//IL_044a: Unknown result type (might be due to invalid IL or missing references)
		//IL_054b: Unknown result type (might be due to invalid IL or missing references)
		//IL_055c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0465: Unknown result type (might be due to invalid IL or missing references)
		//IL_047a: Unknown result type (might be due to invalid IL or missing references)
		//IL_048d: Unknown result type (might be due to invalid IL or missing references)
		//IL_037e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: 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_058a: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: 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_03ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b0: 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_04e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0540: Unknown result type (might be due to invalid IL or missing references)
		//IL_0545: Unknown result type (might be due to invalid IL or missing references)
		//IL_0412: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d3: 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_03e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f1: 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_024d: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0264: 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_026b: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: 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_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_0341: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_028b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02df: 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_02ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: 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_030f: Unknown result type (might be due to invalid IL or missing references)
		//IL_031b: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)rb == (Object)null)
		{
			Pop();
			return;
		}
		bool flag = SimT < 0.35f;
		if (SimT < 0.3f && !straightPhaseOver)
		{
			vel = launchVel;
		}
		else if (EffStraight)
		{
			vel = launchDir * Tuning.StraightSpeed;
		}
		else
		{
			vel = rb.velocity;
			if (((Vector3)(ref vel)).magnitude > 19.5881f)
			{
				vel = ((Vector3)(ref vel)).normalized * 19.5881f;
			}
			if (vel.y > 3f)
			{
				vel.y = 3f;
			}
			if (haveWallPoint)
			{
				float num = Vector3.Dot(rb.position - lastWallPoint, lastWallNormal);
				float num2 = Vector3.Dot(vel, lastWallNormal);
				if (num < radius.Radius + 0.03f)
				{
					vel += lastWallNormal * (0.9f - num2);
				}
				else if (num2 < 0f && num < radius.Radius + 0.5f)
				{
					vel -= lastWallNormal * num2;
				}
			}
			vel = BubbleMotion.StepVelocity(vel, radius.Radius, dt);
		}
		Vector3 position = rb.position;
		Vector3 val = (EffStraight ? launchDir : ((Vector3)(ref vel)).normalized);
		float num3 = (EffStraight ? Tuning.StraightSpeed : ((Vector3)(ref vel)).magnitude);
		RaycastHit val2 = default(RaycastHit);
		if (num3 > 0.05f && Physics.Raycast(position, val, ref val2, radius.Radius + num3 * dt + 0.05f, -5, (QueryTriggerInteraction)1) && ForeignHit(((Object)(object)((RaycastHit)(ref val2)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val2)).collider).transform : null))
		{
			if (EffStraight)
			{
				Vector3 val3 = ((RaycastHit)(ref val2)).point - val * (radius.Radius + 0.05f);
				if (Vector3.Dot(val3 - spawnPos, val) < 0f)
				{
					val3 = spawnPos;
				}
				rb.position = val3;
			}
			if (info.Captures)
			{
				LivingTarget livingTarget = EntityUtil.TargetFromCollider(((RaycastHit)(ref val2)).collider);
				if (livingTarget != null)
				{
					Seal(livingTarget);
					return;
				}
				straightPhaseOver = true;
				radius.Target = Tuning.CastRadius;
				lastWallPoint = ((RaycastHit)(ref val2)).point;
				lastWallNormal = ((RaycastHit)(ref val2)).normal;
				haveWallPoint = true;
				vel = ((RaycastHit)(ref val2)).normal * 0.6f;
				rb.velocity = vel;
				visual.Soap.KickRandom(1.1f);
			}
			else
			{
				rb.velocity = Vector3.zero;
				if (info.Type == BubbleType.Camo)
				{
					EnterHover(Phase.CamoHover);
				}
				else
				{
					EnterDecoyPark();
				}
			}
			return;
		}
		if (info.Captures && !flag)
		{
			LivingTarget livingTarget2 = EntityUtil.FindHomingTarget(position, Tuning.DetectRange, info.Type, spawnPos);
			if (livingTarget2 != null)
			{
				Vector3 val4 = EntityUtil.Center(livingTarget2) - position;
				float magnitude = ((Vector3)(ref val4)).magnitude;
				if (!EffStraight && magnitude > 0.05f)
				{
					vel += val4 / magnitude * 4.47728f * dt;
				}
				if (magnitude <= radius.Radius + Tuning.CapturePad)
				{
					rb.velocity = vel;
					Seal(livingTarget2);
					return;
				}
			}
		}
		bool flag2 = false;
		bool flag3 = false;
		bool groundKnown = false;
		float groundY = 0f;
		RaycastHit val5 = default(RaycastHit);
		if (Physics.Raycast(position + Vector3.up * 1.6789801f, Vector3.down, ref val5, 141.594f, -5, (QueryTriggerInteraction)1))
		{
			float y = ((RaycastHit)(ref val5)).point.y;
			groundKnown = true;
			groundY = y;
			flag3 = ((RaycastHit)(ref val5)).normal.y > 0.6f;
			flag2 = position.y - radius.Radius * 1.5f < y;
			if (!EffStraight && position.y - radius.Radius < y)
			{
				((Vector3)(ref position))..ctor(position.x, y + radius.Radius, position.z);
				rb.position = position;
				if (vel.y < 0f)
				{
					vel = new Vector3(vel.x * 0.9f, (0f - vel.y) * 0.46f, vel.z * 0.9f);
				}
			}
		}
		LimitFlightInflation(position, groundKnown, groundY);
		rb.velocity = vel;
		if (flag)
		{
			return;
		}
		Vector3 val6 = new Vector3(vel.x, 0f, vel.z);
		bool flag4 = ((Vector3)(ref val6)).magnitude <= 1.6789801f;
		switch (info.Type)
		{
		case BubbleType.Camo:
		{
			bool num4;
			if (!EffStraight)
			{
				if (flag4)
				{
					goto IL_05f1;
				}
				num4 = SimT >= 1.8000001f;
			}
			else
			{
				num4 = SimT >= 3.5f;
			}
			if (!num4)
			{
				break;
			}
			goto IL_05f1;
		}
		case BubbleType.Decoy:
		{
			bool num5;
			if (!EffStraight)
			{
				if (flag4 && SimT > 0.8f)
				{
					goto IL_064d;
				}
				if (!(flag2 && flag3))
				{
					goto IL_0640;
				}
				num5 = SimT > 1.2f;
			}
			else
			{
				num5 = SimT >= 3.5f;
			}
			if (!num5)
			{
				goto IL_0640;
			}
			goto IL_064d;
		}
		default:
			{
				if (EffStraight && SimT >= 3.5f)
				{
					straightPhaseOver = true;
					radius.Target = Tuning.CastRadius;
				}
				else if (!EffStraight && flag4 && SimT > 1.2f)
				{
					EnterHover(Phase.FloatPark);
				}
				break;
			}
			IL_0640:
			if (!(SimT >= 6f))
			{
				break;
			}
			goto IL_064d;
			IL_064d:
			EnterDecoyPark();
			break;
			IL_05f1:
			EnterHover(Phase.CamoHover);
			break;
		}
	}

	private void EnterHover(Phase p)
	{
		//IL_0034: 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_0039: 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_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_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_0062: 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_0092: Unknown result type (might be due to invalid IL or missing references)
		phase = p;
		hovering = true;
		Vector3 val = (((Object)(object)rb != (Object)null) ? rb.position : Root.transform.position);
		hoverY = val.y;
		hoverXZ = val;
		if ((Object)(object)rb != (Object)null)
		{
			vel = rb.velocity;
			rb.isKinematic = true;
		}
		RaycastHit val2 = default(RaycastHit);
		if (Physics.Raycast(val, Vector3.down, ref val2, 60f, -5, (QueryTriggerInteraction)1))
		{
			hoverGroundY = ((RaycastHit)(ref val2)).point.y;
		}
		if (p == Phase.CamoHover || p == Phase.FloatPark)
		{
			radius.Target = Tuning.CastRadius;
		}
	}

	private float FloorLift(float y)
	{
		if (hoverGroundY > float.MinValue)
		{
			return Mathf.Max(y, hoverGroundY + radius.Radius * 0.99f);
		}
		return y;
	}

	private void StepParkedInflation(float dt)
	{
		if (!(hoverGroundY <= float.MinValue))
		{
			float num = hoverGroundY + Tuning.CastRadius * 0.99f;
			if (hoverY < num)
			{
				hoverY = Mathf.MoveTowards(hoverY, num, 1.1f * dt);
			}
			hoverY = FloorLift(hoverY);
			radius.Target = Mathf.Clamp(hoverY - hoverGroundY, Tuning.BaseRadius * 0.6f, Tuning.CastRadius);
		}
	}

	private static float DecoyFit(float avatarHeight)
	{
		return Mathf.Max(avatarHeight * 0.5f + Tuning.FitMargin * 0.6f, 0.95f);
	}

	private void EnterDecoyPark()
	{
		//IL_002d: 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_0032: 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)
		//IL_0034: 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_006f: 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_008d: 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)
		//IL_00cc: 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)
		EnterHover(Phase.DecoyParked);
		Vector3 val = (((Object)(object)rb != (Object)null) ? rb.position : Root.transform.position);
		RaycastHit val2 = default(RaycastHit);
		if (Physics.Raycast(val, Vector3.down, ref val2, 6f + radius.Radius, -5, (QueryTriggerInteraction)1) && ((RaycastHit)(ref val2)).normal.y > 0.6f)
		{
			decoyFloorY = ((RaycastHit)(ref val2)).point.y;
			decoyBody = EntityUtil.SpawnHologramOf(casterRig, ((RaycastHit)(ref val2)).point, launchDir, out var height);
			if ((Object)(object)decoyBody != (Object)null)
			{
				decoyLanded = true;
				radius.Target = DecoyFit(height);
				hoverXZ = ((RaycastHit)(ref val2)).point;
				hoverY = val.y;
				return;
			}
		}
		radius.Target = DecoyFit(EntityUtil.AvatarHeight(casterRig));
	}

	private void Seal(LivingTarget prey)
	{
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: 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_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02be: Unknown result type (might be due to invalid IL or missing references)
		//IL_02da: Unknown result type (might be due to invalid IL or missing references)
		captive = prey;
		captureAt = Now;
		struggles = 0;
		healedTotal = 0f;
		nextNpcStruggle = Now + 0.7f;
		nextHealChunk = Now + 2f;
		reviveAt = ((prey.Kind == TargetKind.Corpse && info.Type == BubbleType.Healing) ? (Now + 6f) : (-1f));
		float num = (prey.IsPlayer ? Mathf.Max(EntityUtil.PlayerHeight() * 0.5f + Tuning.FitMargin * 0.6f, 0.95f) : Mathf.Max(EntityUtil.EnclosingRadius(prey) * Tuning.CaptureSizeMult + Tuning.FitMargin, 0.45f));
		radius.Target = num;
		radius.Radius = Mathf.Max(radius.Radius, num * 0.6f);
		EntityUtil.SetCaptured(prey, captured: true);
		if ((Object)(object)solidCollider != (Object)null)
		{
			foreach (Collider item in EntityUtil.AllColliders(prey))
			{
				if ((Object)(object)item != (Object)null)
				{
					Physics.IgnoreCollision((Collider)(object)solidCollider, item, true);
				}
			}
			if (prey.IsPlayer)
			{
				EntityUtil.IgnoreHeldItems(((Component)solidCollider).gameObject);
			}
		}
		if (remote)
		{
			hovering = true;
			visual.Soap.Kick(1.15f / Mathf.Max(0.3f, info.MembraneStrength));
			phase = Phase.Holding;
			return;
		}
		Vector3 val = EntityUtil.Center(prey);
		if (!prey.IsPlayer && playerSolid && (Object)(object)solidCollider != (Object)null && EntityUtil.PlayerHeadDistance(val) < num + 0.6f)
		{
			playerSolid = false;
			EntityUtil.IgnoreCollisionsWith(((Component)solidCollider).gameObject, EntityUtil.PlayerRoot());
		}
		float num2 = Mathf.Clamp01(9f / (9f + EntityUtil.TotalMass(prey)));
		ascendScale = (prey.IsPlayer ? 1f : Mathf.Lerp(0.4f, 1.15f, num2));
		float num3 = 1.6789801f;
		if (prey.IsPlayer)
		{
			num3 = 0.9234391f;
		}
		else if (prey.Kind == TargetKind.Item)
		{
			num3 = 1.6789801f * (0.25f + 0.95f * num2);
		}
		else if (num > 1.11932f)
		{
			num3 = Mathf.Min(9.51422f, 1.6789801f + (num - 1.11932f) * 1.6f);
		}
		hoverY = val.y + num3;
		hoverXZ = val;
		hovering = false;
		if ((Object)(object)rb != (Object)null)
		{
			rb.velocity = Vector3.zero;
			rb.isKinematic = true;
			rb.position = val;
		}
		visual.Soap.Kick(1.15f / Mathf.Max(0.3f, info.MembraneStrength));
		phase = Phase.Holding;
	}

	private void StepHolding(float dt)
	{
		//IL_002e: 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)
		//IL_005f: 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_0064: 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_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_00e2: 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_0105: 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_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: 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_0194: 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_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: 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_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: 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_0464: Unknown result type (might be due to invalid IL or missing references)
		if (!EntityUtil.IsValid(captive))
		{
			captive = null;
			ReleaseOrPop();
			return;
		}
		Vector3 val = default(Vector3);
		if (remote)
		{
			val = Root.transform.position;
		}
		else
		{
			Vector3 val2 = (((Object)(object)rb != (Object)null) ? rb.position : Root.transform.position);
			float num;
			if (hovering)
			{
				num = hoverY + BubbleMotion.HoverBob(SimT);
			}
			else
			{
				num = Mathf.MoveTowards(val2.y, hoverY, 2.23864f * ascendScale * dt);
				if (Mathf.Abs(num - hoverY) < 0.02f)
				{
					hovering = true;
				}
			}
			Vector3 val3 = BubbleMotion.IdleOffset(SimT, wobSeed);
			((Vector3)(ref val))..ctor(hoverXZ.x + val3.x, num + val3.y * 0.5f, hoverXZ.z + val3.z);
			Vector3 val4 = EntityUtil.Center(captive);
			val = Vector3.Lerp(val, val4, 0.3f);
		}
		if (captive.IsPlayer && Now >= nextReassert)
		{
			nextReassert = Now + 0.5f;
			EntityUtil.ReassertHold(captive);
		}
		if (!remote)
		{
			if ((Object)(object)rb != (Object)null)
			{
				rb.MovePosition(val);
			}
			else
			{
				Root.transform.position = val;
			}
		}
		bool limp = EntityUtil.IsDead(captive) || captive.Kind == TargetKind.Item;
		Vector3 val5 = BubbleMotion.OccupantOffset(SimT, wobSeed, Mathf.Clamp01(radius.Radius / 1.2f));
		EntityUtil.HoldStep(captive, dt, val + val5, radius.Radius, limp);
		if (info.Type == BubbleType.Healing && reviveAt < 0f && !captive.IsPlayer && captive.Kind != TargetKind.Item && EntityUtil.IsDead(captive))
		{
			reviveAt = Now + 6f;
		}
		if (reviveAt > 0f && Now >= reviveAt)
		{
			reviveAt = -1f;
			if (EntityUtil.Revive(captive))
			{
				visual.Soap.Kick(1.2f);
			}
		}
		if ((captive.Kind != TargetKind.Npc || EntityUtil.IsDead(captive)) && captive.Kind != TargetKind.Player)
		{
			OuterTouchHeal(val, dt);
			return;
		}
		bool flag = false;
		if (captive.IsPlayer)
		{
			if (EntityUtil.ConsumePlayerStruggle())
			{
				flag = true;
			}
		}
		else if (Now >= nextNpcStruggle)
		{
			nextNpcStruggle = Now + 0.7f;
			flag = true;
		}
		if (flag)
		{
			struggles++;
			visual.Soap.Kick(1.4f / Mathf.Max(0.3f, info.MembraneStrength));
			if (struggles >= 14)
			{
				ReleaseOrPop();
				return;
			}
		}
		if (info.Type == BubbleType.Normal && captive.Kind == TargetKind.Npc)
		{
			suffBank += 4f * dt;
			if (suffBank >= 1f)
			{
				float num2 = Mathf.Floor(suffBank);
				suffBank -= num2;
				EntityUtil.Damage(captive, num2);
			}
		}
		else if (info.Type == BubbleType.Healing)
		{
			if (Now >= nextHealChunk)
			{
				nextHealChunk = Now + 2f;
				EntityUtil.Heal(captive, 10f);
				healedTotal += 10f;
				visual.Soap.Kick(0.35f);
			}
			float num3 = EntityUtil.HealthFrac(captive);
			if ((num3 >= 0f && num3 >= 0.999f) || healedTotal >= 60f)
			{
				ReleaseOrPop();
				return;
			}
		}
		OuterTouchHeal(val, dt);
	}

	private void OuterTouchHeal(Vector3 center, float dt)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		if (info.Type != BubbleType.Healing)
		{
			return;
		}
		LivingTarget livingTarget = EntityUtil.PlayerIfNear(center, radius.Radius + 0.35f);
		if (livingTarget != null && (captive == null || !captive.IsPlayer))
		{
			healBank += 3f * dt;
			if (healBank >= 1f)
			{
				float num = Mathf.Floor(healBank);
				healBank -= num;
				EntityUtil.Heal(livingTarget, num);
			}
		}
	}

	private float ProximityFade(Vector3 center, float floor)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		float num = EntityUtil.PlayerHeadDistance(center);
		float num2 = 1f - Mathf.Clamp01((num - Tuning.DecoyHideDistance) / (Tuning.DecoyHideDistance * 1.2f));
		return Mathf.Max(floor, num2);
	}

	private void StepFloatPark(float dt)
	{
		//IL_0002: 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_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_0067: 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_007a: 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_00c5: 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)
		vel *= Mathf.Exp(-4.5f * dt);
		hoverXZ += new Vector3(vel.x, 0f, vel.z) * dt;
		StepParkedInflation(dt);
		Vector3 val = BubbleMotion.IdleOffset(SimT, wobSeed);
		Vector3 val2 = default(Vector3);
		((Vector3)(ref val2))..ctor(hoverXZ.x + val.x, hoverY + BubbleMotion.HoverBob(SimT), hoverXZ.z + val.z);
		if ((Object)(object)rb != (Object)null)
		{
			rb.MovePosition(val2);
		}
		OuterTouchHeal(val2, dt);
	}

	private void StepCamoHover(float dt)
	{
		//IL_0002: 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_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_0067: 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_007a: 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_00c4: 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_00dd: 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_013d: 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)
		vel *= Mathf.Exp(-4.5f * dt);
		hoverXZ += new Vector3(vel.x, 0f, vel.z) * dt;
		StepParkedInflation(dt);
		Vector3 val = BubbleMotion.IdleOffset(SimT, wobSeed);
		Vector3 val2 = default(Vector3);
		((Vector3)(ref val2))..ctor(hoverXZ.x + val.x, hoverY + BubbleMotion.HoverBob(SimT), hoverXZ.z + val.z);
		if ((Object)(object)rb != (Object)null)
		{
			rb.MovePosition(val2);
		}
		if (EntityUtil.PlayerHeadInside(val2, radius.Radius + 0.28f))
		{
			EntityUtil.CloakPlayerTick(val2, Tuning.DetectRange * 2f);
		}
		if (Now >= nextCloak)
		{
			nextCloak = Now + 0.25f;
			EntityUtil.CloakRigsInside(val2, radius.Radius, cloakedRigs);
		}
		visual.SetFade(ProximityFade(val2, 0f));
		OuterTouchHeal(val2, dt);
	}

	private void StepDecoyParked(float dt)
	{
		//IL_006e: 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_0087: 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_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: 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)
		float num = ((decoyFloorY > float.MinValue) ? (decoyFloorY + radius.Radius * 0.98f) : (hoverY - 3f));
		hoverY = Mathf.MoveTowards(hoverY, num, 0.12f * dt);
		float num2 = (decoyLanded ? 0.35f : 1f);
		Vector3 val = BubbleMotion.IdleOffset(SimT, wobSeed) * num2;
		Vector3 val2 = default(Vector3);
		((Vector3)(ref val2))..ctor(hoverXZ.x + val.x, hoverY + BubbleMotion.HoverBob(SimT) * num2, hoverXZ.z + val.z);
		if ((Object)(object)rb != (Object)null)
		{
			rb.MovePosition(val2);
		}
		visual.SetFade(ProximityFade(val2, decoyLanded ? 0f : 0.35f));
		EntityUtil.AttractAggro(Root, val2, Tuning.DecoyBurstRange * 1.5f);
	}

	private void DetectShots()
	{
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: 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_0050: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: 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_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		if ((!EffStraight || phase != Phase.Flight) && Now < nextShotScan)
		{
			return;
		}
		nextShotScan = Now + 0.1f;
		Vector3 val = (((Object)(object)rb != (Object)null) ? rb.position : Root.transform.position);
		bool flag = info.Captures && SimT >= 0.06f && (phase == Phase.Flight || phase == Phase.FloatPark);
		if (flag && info.Type == BubbleType.Healing)
		{
			LivingTarget livingTarget = EntityUtil.PlayerDeepInside(val, radius.Radius, spawnPos);
			if (livingTarget != null)
			{
				Seal(livingTarget);
				return;
			}
		}
		Il2CppReferenceArray<Collider> val2 = Physics.OverlapSphere(val, radius.Radius * 1.2f + 0.2f, -5, (QueryTriggerInteraction)1);
		if (val2 == null)
		{
			return;
		}
		foreach (Collider item in (Il2CppArrayBase<Collider>)(object)val2)
		{
			if ((Object)(object)item == (Object)null)
			{
				continue;
			}
			Rigidbody attachedRigidbody = item.attachedRigidbody;
			if ((Object)(object)attachedRigidbody == (Object)null || (captive != null && EntityUtil.Owns(captive, attachedRigidbody)) || EntityUtil.IsGunPart(((Component)item).transform))
			{
				continue;
			}
			Vector3 velocity;
			try
			{
				velocity = attachedRigidbody.velocity;
				if (((Vector3)(ref velocity)).magnitude > 1.2f && (Object)(object)((Component)item).GetComponentInParent<StabSlash>() != (Object)null)
				{
					Pop();
					break;
				}
			}
			catch
			{
			}
			if (attachedRigidbody.mass <= 0.6f)
			{
				velocity = attachedRigidbody.velocity;
				if (((Vector3)(ref velocity)).magnitude >= 25f)
				{
					if (!(Now - lastShotAt < 0.09f))
					{
						lastShotAt = Now;
						hp -= 30f;
						visual.Soap.KickRandom(0.8f / Mathf.Max(0.3f, info.MembraneStrength));
						if (hp <= 0f)
						{
							Pop();
						}
						break;
					}
					continue;
				}
			}
			if (flag)
			{
				LivingTarget livingTarget2 = EntityUtil.TargetFromCollider(item);
				if (livingTarget2 != null)
				{
					Seal(livingTarget2);
					break;
				}
			}
		}
	}

	public void Pop()
	{
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: 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_00d8: 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_0132: 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_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Expected O, but got Unknown
		if (phase == Phase.Popped)
		{
			return;
		}
		if (remote)
		{
			phase = Phase.Popped;
			if (captive != null)
			{
				EntityUtil.SetCaptured(captive, captured: false);
				captive = null;
			}
			if ((Object)(object)decoyBody != (Object)null)
			{
				Object.Destroy((Object)(object)decoyBody);
				decoyBody = null;
			}
			EntityUtil.UncloakAll(cloakedRigs);
			visual.SetFade(1f);
			Root = null;
			return;
		}
		phase = Phase.Popped;
		Vector3 val = (((Object)(object)Root != (Object)null) ? Root.transform.position : Vector3.zero);
		if (captive != null)
		{
			EntityUtil.SetCaptured(captive, captured: false);
			captive = null;
		}
		EntityUtil.UncloakAll(cloakedRigs);
		if (info.Type == BubbleType.Decoy)
		{
			EntityUtil.DecoyBurst(val, Tuning.DecoyBurstRange, 4.5f);
		}
		if ((Object)(object)decoyBody != (Object)null)
		{
			Object.Destroy((Object)(object)decoyBody);
			decoyBody = null;
		}
		visual.SetFade(1f);
		if ((Object)(object)popParticles != (Object)null)
		{
			GameObject obj = Object.Instantiate<GameObject>(((Component)popParticles).gameObject, val, Quaternion.identity);
			obj.SetActive(true);
			ParticleSystem component = obj.GetComponent<ParticleSystem>();
			if ((Object)(object)component != (Object)null)
			{
				component.main.startColor = new MinMaxGradient(info.ShellColor);
				component.Play();
			}
			Object.Destroy((Object)(object)obj, 3f);
		}
		if ((Object)(object)popClip != (Object)null)
		{
			AudioSource.PlayClipAtPoint(popClip, val, 0.9f);
		}
		if ((Object)(object)Root != (Object)null && !FusionGate.TryNetworkDespawn(Root))
		{
			EntityUtil.Despawn(Root);
		}
		Root = null;
	}
}
public static class BubbleMotion
{
	public const float StudsToMeters = 0.27983f;

	public static float RefRadius = 0.55f;

	public const float GNet = 0.727558f;

	public const float AirDrag = 1.15f;

	public const float GroundBounce = 0.46f;

	public const float BounceFriction = 0.9f;

	public const float MaxSpeed = 19.5881f;

	public const float WobBob = 0.097940505f;

	public const float WobSway = 0.0447728f;

	public const float WobRate = 1.5f;

	public const float BobAmp = 0.097940505f;

	public const float BobRate = 1.4f;

	public const float OccSway = 0.0783524f;

	public const float OccBob = 0.0615626f;

	public const float OccTilt = (float)Math.PI / 30f;

	public const float OccRate = 0.85f;

	public const float OccLean = 0.34906584f;

	public static Vector3 BuoyantGravity(float radius)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Pow(radius / RefRadius, 1.5f);
		return new Vector3(0f, -0.727558f / Mathf.Max(0.6f, num), 0f);
	}

	public static Vector3 StepVelocity(Vector3 vel, float radius, float dt)
	{
		//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_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_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0047: 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_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)
		vel += BuoyantGravity(radius) * dt;
		vel *= Mathf.Exp(-1.15f * dt);
		float magnitude = ((Vector3)(ref vel)).magnitude;
		if (magnitude > 19.5881f)
		{
			vel *= 19.5881f / magnitude;
		}
		return vel;
	}

	public static Vector3 IdleOffset(float t, float seed)
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(Mathf.Sin(t * 1.5f * 0.8f + seed) * 0.0447728f, Mathf.Sin(t * 1.5f + seed) * 0.097940505f, Mathf.Cos(t * 1.5f * 0.9f + seed) * 0.0447728f);
	}

	public static float HoverBob(float t)
	{
		return Mathf.Sin(t * 1.4f) * 0.097940505f;
	}

	public static Vector3 OccupantOffset(float t, float seed, float scale = 1f)
	{
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Sin(0.34906584f) * 0.0615626f * scale;
		return new Vector3(Mathf.Sin(t * 0.85f + seed) * 0.0783524f * scale, Mathf.Sin(t * 0.85f * 1.7f + seed + 1.3f) * 0.0615626f * scale, Mathf.Cos(t * 0.85f * 0.85f + seed + 0.6f) * 0.0783524f * scale - num);
	}

	public static Quaternion OccupantTilt(float t, bool withLean)
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Sin(t * 0.85f * 0.9f + 0.4f) * ((float)Math.PI / 30f);
		float num2 = Mathf.Cos(t * 0.85f * 1.1f) * ((float)Math.PI / 30f);
		return Quaternion.Euler((0f - (withLean ? 0.34906584f : 0f) + num2) * 57.29578f, 0f, num * 57.29578f);
	}
}
public class SoapOscillator
{
	private const float Omega = 4.4f;

	private const float Zeta = 0.04f;

	private const float MaxAmp = 0.3f;

	private const float AirTurb = 0.05f;

	private const float AirFreq = 0.55f;

	private const float RamFlatten = 0.22f;

	private const float SagAmp = 0.035f;

	private readonly float[] x = new float[3];

	private readonly float[] v = new float[3];

	private readonly float seed;

	private float t;

	public SoapOscillator(float seed)
	{
		this.seed = seed;
	}

	public void Kick(float amount)
	{
		v[1] -= amount * 4.4f;
		v[0] += amount * 4.4f * 0.5f;
		v[2] += amount * 4.4f * 0.5f;
	}

	public void KickRandom(float amount)
	{
		int num = Random.Range(0, 3);
		v[num] -= amount * 4.4f;
		v[(num + 1) % 3] += amount * 4.4f * 0.5f;
		v[(num + 2) % 3] += amount * 4.4f * 0.5f;
	}

	public Vector3 Step(float dt, float radius, float speedFrac, bool occupied)
	{
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		t += dt;
		dt = Mathf.Min(dt, 1f / 30f);
		float num = 4.4f * Mathf.Clamp(Mathf.Pow(BubbleMotion.RefRadius / Mathf.Max(0.05f, radius), 1.5f), 0.4f, 2.4f);
		float num2 = 0.05f * (occupied ? 1.6f : 1f);
		for (int i = 0; i < 3; i++)
		{
			float num3 = Mathf.PerlinNoise(t * 0.55f + seed + (float)i * 7.3f, seed * 1.7f + (float)i * 3.1f) - 0.5f;
			float num4 = 0.35f + 2.4f * num3 * num3;
			float num5 = num3 * num4 * num2 * num * num;
			if (i == 1)
			{
				num5 -= 0.035f * num * num;
				num5 -= 0.22f * speedFrac * num * num;
			}
			v[i] += (num5 - 0.08f * num * v[i] - num * num * x[i]) * dt;
			x[i] += v[i] * dt;
			x[i] = Mathf.Clamp(x[i], -0.3f, 0.3f);
		}
		float num6 = 1f + x[0];
		float num7 = 1f + x[1];
		float num8 = 1f + x[2];
		float num9 = Mathf.Pow(Mathf.Max(0.05f, num6 * num7 * num8), 1f / 3f);
		return new Vector3(num6 / num9, num7 / num9, num8 / num9);
	}
}
public class RadiusSpring
{
	private const float Stiffness = 13f;

	private const float Damping = 5.5f;

	public float Radius;

	public float Target;

	private float vel;

	private readonly float min;

	private readonly float max;

	public RadiusSpring(float start, float min, float max)
	{
		Radius = start;
		Target = start;
		this.min = min;
		this.max = max;
	}

	public void Step(float dt)
	{
		float num = (Target - Radius) * 13f - vel * 5.5f;
		vel += num * dt;
		Radius = Mathf.Clamp(Radius + vel * dt, min, max);
	}
}
public enum BubbleType
{
	Normal,
	Healing,
	Camo,
	Decoy
}
public class BubbleTypeInfo
{
	public BubbleType Type;

	public string Name;

	public Color ShellColor;

	public float ShellAlpha;

	public float Hp;

	public float MembraneStrength;

	public bool Captures;

	public bool Solid;

	public string Glyph = "";

	public string GlyphFallback = "";

	public Color GlyphColor;

	public int GlyphCount;

	public float GlyphAlpha;

	public bool GlyphBanded;

	public static readonly BubbleTypeInfo[] All = new BubbleTypeInfo[4]
	{
		new BubbleTypeInfo
		{
			Type = BubbleType.Normal,
			Name = "Normal",
			ShellColor = new Color(0.47058824f, 44f / 51f, 47f / 51f),
			ShellAlpha = 0.3f,
			Hp = 150f,
			MembraneStrength = 1f,
			Captures = true,
			Solid = true
		},
		new BubbleTypeInfo
		{
			Type = BubbleType.Healing,
			Name = "Healing",
			ShellColor = new Color(14f / 15f, 0.5803922f, 0.7372549f),
			ShellAlpha = 0.3f,
			Hp = 140f,
			MembraneStrength = 0.85f,
			Captures = true,
			Solid = true
		},
		new BubbleTypeInfo
		{
			Type = BubbleType.Camo,
			Name = "Camo",
			ShellColor = new Color(0.3372549f, 0.76862746f, 32f / 85f),
			ShellAlpha = 0.5f,
			Hp = 120f,
			MembraneStrength = 1.5f,
			Captures = false,
			Solid = false
		},
		new BubbleTypeInfo
		{
			Type = BubbleType.Decoy,
			Name = "Decoy",
			ShellColor = new Color(0.5882353f, 2f / 3f, 38f / 51f),
			ShellAlpha = 0.3f,
			Hp = 80f,
			MembraneStrength = 0.6f,
			Captures = false,
			Solid = false
		}
	};

	public static BubbleTypeInfo Get(BubbleType t)
	{
		return All[(int)t];
	}

	public static BubbleType Next(BubbleType t)
	{
		return (BubbleType)((int)(t + 1) % All.Length);
	}
}
public static class Tuning
{
	public static float BaseRadius = 0.55f;

	public static float CastRadius = 3.2f;

	public const float MinRadius = 0.18f;

	public const float MaxRadius = 4.5f;

	public static float FitMargin = 0.55f;

	public static float CaptureSizeMult = 1.3f;

	public const float MuzzleOffset = 0.22f;

	public const float LaunchLockSecs = 0.3f;

	public const float GraceSecs = 0.35f;

	public const float PlayerCaptureMinDist = 1f;

	public const float MaxContactRise = 3f;

	public static float TintOpacity = 0.5f;

	public static int MaxActiveBubbles = 4;

	public static float DetectRange = 7.2755804f;

	public const float Homing = 4.47728f;

	public static float CapturePad = 0.97940505f;

	public const int EscapeNeeded = 14;

	public const float NpcStruggleEvery = 0.7f;

	public const float SuffocateInside = 2f;

	public const float SuffocateEnveloped = 4f;

	public const float EnvelopedFrac = 0.55f;

	public const float HoverRise = 1.6789801f;

	public const float AscendVel = 2.23864f;

	public const float NormalFitR = 1.11932f;

	public const float BigRisePerMeter = 1.6f;

	public const float BigRiseMax = 9.51422f;

	public const float InsideHealChunk = 10f;

	public const float InsideHealInterval = 2f;

	public const float OuterHealPerSec = 3f;

	public const float CamoSettleSpeed = 1.6789801f;

	public const float CamoSettleSecs = 0.6f;

	public const float CamoHoverDamp = 4.5f;

	public static float DecoyBurstRange = 10f;

	public const float DecoyBurstShove = 4.5f;

	public static float DecoyHideDistance = 2.5f;

	public const float DecoyGroundSearch = 6f;

	public const float WalkableNormalY = 0.6f;

	public const float DecoySinkRate = 0.12f;

	public const float ReviveTime = 6f;

	public static float StraightSpeed = 55f;

	public const float StraightTimeout = 3.5f;

	public static float ChargeSpeedMult = 2.5f;

	public static bool CapturePlayer = true;

	public const float GroundRayUp = 1.6789801f;

	public const float GroundRayDown = 139.91501f;
}
public enum TargetKind
{
	Npc,
	Corpse,
	Player,
	Item
}
public class LivingTarget
{
	public TargetKind Kind;

	public AIBrain Brain;

	public GameObject Root;

	public int RootId;

	public List<Rigidbody> Bodies;

	public List<Collider> Colliders;

	public bool[] HadGravity;

	public string SavedNavState;

	public bool IsPlayer => Kind == TargetKind.Player;
}
public static class EntityUtil
{
	private static readonly HashSet<int> capturedRoots = new HashSet<int>();

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

	private static readonly List<AIBrain> brainCache = new List<AIBrain>();

	private static float brainCacheAt = -99f;

	private static readonly List<MarrowEntity> entityCache = new List<MarrowEntity>();

	private static float entityCacheAt = -99f;

	private static LivingTarget playerCache;

	private static float playerCacheAt = -99f;

	private static bool warnedClientCaptures;

	private static readonly List<RigManager> rigCache = new List<RigManager>();

	private static float rigCacheAt = -99f;

	private static readonly Dictionary<int, List<Renderer>> cloakedRenderers = new Dictionary<int, List<Renderer>>();

	private static bool struggleLatch;

	private static bool triggerWasDown;

	private static readonly string[] HologramKeepTypes = new string[5] { "UnityEngine.Transform", "UnityEngine.RectTransform", "UnityEngine.SkinnedMeshRenderer", "UnityEngine.MeshRenderer", "UnityEngine.MeshFilter" };

	private static float lastCloakTick;

	private static float lastAggroTick;

	public static void OnInit()
	{
		Hooking.OnNPCBrainDie += delegate(AIBrain brain)
		{
			if ((Object)(object)brain != (Object)null)
			{
				deadBrains.Add(((Object)brain).GetInstanceID());
			}
		};
		Hooking.OnNPCBrainResurrected += delegate(AIBrain brain)
		{
			if ((Object)(object)brain != (Object)null)
			{
				deadBrains.Remove(((Object)brain).GetInstanceID());
			}
		};
		Hooking.OnLevelUnloaded += delegate
		{
			capturedRoots.Clear();
			deadBrains.Clear();
			brainCache.Clear();
			entityCache.Clear();
			brainCacheAt = (entityCacheAt = -99f);
			playerCache = null;
			rigCache.Clear();
			rigCacheAt = -99f;
			cloakedRenderers.Clear();
		};
	}

	private static List<AIBrain> Brains()
	{
		if (Time.time - brainCacheAt > 2f)
		{
			brainCache.Clear();
			Il2CppArrayBase<AIBrain> val = Object.FindObjectsOfType<AIBrain>();
			if (val != null)
			{
				foreach (AIBrain item in val)
				{
					if ((Object)(object)item != (Object)null)
					{
						brainCache.Add(item);
					}
				}
			}
			brainCacheAt = Time.time;
		}
		return brainCache;
	}

	private static List<MarrowEntity> Entities()
	{
		if (Time.time - entityCacheAt > 3f)
		{
			entityCache.Clear();
			Il2CppArrayBase<MarrowEntity> val = Object.FindObjectsOfType<MarrowEntity>();
			if (val != null)
			{
				foreach (MarrowEntity item in val)
				{
					if ((Object)(object)item != (Object)null)
					{
						entityCache.Add(item);
					}
				}
			}
			entityCacheAt = Time.time;
		}
		return entityCache;
	}

	private static bool BrainDead(AIBrain brain)
	{
		if ((Object)(object)brain == (Object)null)
		{
			return true;
		}
		if (deadBrains.Contains(((Object)brain).GetInstanceID()))
		{
			return true;
		}
		try
		{
			BehaviourBaseNav behaviour = brain.behaviour;
			object obj = ((behaviour != null) ? behaviour.health : null);
			if (obj != null && TryReadFloat(obj, out var val, "curr_Health", "cur_hp", "curr_health") && TryReadFloat(obj, out var val2, "max_Health", "max_hp", "max_health") && val2 > 0f)
			{
				return val <= 0f;
			}
		}
		catch
		{
		}
		return false;
	}

	private static LivingTarget Build(AIBrain brain)
	{
		GameObject val = null;
		try
		{
			MarrowEntity componentInParent = ((Component)brain).GetComponentInParent<MarrowEntity>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				val = ((Component)componentInParent).gameObject;
			}
		}
		catch
		{
		}
		if ((Object)(object)val == (Object)null)
		{
			val = ((Component)((Component)brain).transform.root).gameObject;
		}
		return FillBodies(new LivingTarget
		{
			Kind = (BrainDead(brain) ? TargetKind.Corpse : TargetKind.Npc),
			Brain = brain,
			Root = val,
			RootId = ((Object)val).GetInstanceID()
		});
	}

	private static LivingTarget BuildItem(MarrowEntity entity)
	{
		GameObject gameObject = ((Component)entity).gameObject;
		return FillBodies(new LivingTarget
		{
			Kind = TargetKind.Item,
			Brain = null,
			Root = gameObject,
			RootId = ((Object)gameObject).GetInstanceID()
		});
	}

	private static LivingTarget FillBodies(LivingTarget t)
	{
		t.Bodies = new List<Rigidbody>();
		t.Colliders = new List<Collider>();
		foreach (Rigidbody componentsInChild in t.Root.GetComponentsInChildren<Rigidbody>(false))
		{
			if ((Object)(object)componentsInChild != (Object)null)
			{
				t.Bodies.Add(componentsInChild);
			}
		}
		foreach (Collider componentsInChild2 in t.Root.GetComponentsInChildren<Collider>(false))
		{
			if ((Object)(object)componentsInChild2 != (Object)null)
			{
				t.Colliders.Add(componentsInChild2);
			}
		}
		if (t.Bodies.Count <= 0)
		{
			return null;
		}
		return t;
	}

	private static LivingTarget BuildPlayer()
	{
		if (playerCache != null && (Object)(object)playerCache.Root != (Object)null && Time.time - playerCacheAt < 2f)
		{
			return playerCache;
		}
		PhysicsRig physicsRig = Player.PhysicsRig;
		if ((Object)(object)physicsRig == (Object)null)
		{
			return null;
		}
		GameObject gameObject = ((Component)physicsRig).gameObject;
		playerCache = FillBodies(new LivingTarget
		{
			Kind = TargetKind.Player,
			Brain = null,
			Root = gameObject,
			RootId = ((Object)gameObject).GetInstanceID()
		});
		playerCacheAt = Time.time;
		return playerCache;
	}

	public static bool IsPlayerPart(Transform t)
	{
		try
		{
			return (Object)(object)t != (Object)null && (Object)(object)((Component)t).GetComponentInParent<PhysicsRig>() != (Object)null;
		}
		catch
		{
			return false;
		}
	}

	public static bool IsGunPart(Transform t)
	{
		if ((Object)(object)t == (Object)null)
		{
			return false;
		}
		Transform val = t;
		while ((Object)(object)val != (Object)null)
		{
			foreach (GunManager item in GunManager.Active)
			{
				if (!item.Dead && (Object)(object)((Component)val).gameObject == (Object)(object)item.Root)
				{
					return true;
				}
			}
			val = val.parent;
		}
		return false;
	}

	private static bool IsHeldByPlayer(GameObject root)
	{
		try
		{
			return IsHeldBy(Player.LeftHand, root) || IsHeldBy(Player.RightHand, root);
		}
		catch
		{
			return false;
		}
	}

	private static bool ItemEligible(MarrowEntity e, out float roughRadius)
	{
		roughRadius = 0f;
		if ((Object)(object)e == (Object)null)
		{
			return false;
		}
		GameObject gameObject = ((Component)e).gameObject;
		if ((Object)(object)gameObject == (Object)null || !gameObject.activeInHierarchy)
		{
			return false;
		}
		if (capturedRoots.Contains(((Object)gameObject).GetInstanceID()))
		{
			return false;
		}
		string name = ((Object)gameObject).name;
		if (name.Contains("BubbleProjectile") || name.Contains("BubbleGun"))
		{
			return false;
		}
		try
		{
			if ((Object)(object)gameObject.GetComponentInChildren<AIBrain>(true) != (Object)null)
			{
				return false;
			}
			if ((Object)(object)gameObject.GetComponentInParent<PhysicsRig>() != (Object)null)
			{
				return false;
			}
		}
		catch
		{
		}
		if (IsHeldByPlayer(gameObject))
		{
			return false;
		}
		foreach (GunManager item in GunManager.Active)
		{
			if (!item.Dead && (Object)(object)item.Root == (Object)(object)gameObject)
			{
				return false;
			}
		}
		bool flag = false;
		foreach (Rigidbody componentsInChild in gameObject.GetComponentsInChildren<Rigidbody>(false))
		{
			if ((Object)(object)componentsInChild != (Object)null && !componentsInChild.isKinematic)
			{
				flag = true;
				break;
			}
		}
		if (!flag)
		{
			return false;
		}
		return true;
	}

	private static bool CaptureAuthority()
	{
		if (FusionGate.IsAuthority)
		{
			return true;
		}
		if (!warnedClientCaptures)
		{
			warnedClientCaptures = true;
			MelonLogger.Msg("[BubbleBlaster] Fusion lobby client: captures are host-only");
		}
		return false;
	}

	public static LivingTarget FindHomingTarget(Vector3 pos, float range, BubbleType type, Vector3 spawnPos)
	{
		//IL_003a: 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)
		if (!CaptureAuthority())
		{
			return null;
		}
		AIBrain val = null;
		AIBrain val2 = null;
		float num = range;
		float num2 = range;
		foreach (AIBrain item in Brains())
		{
			if ((Object)(object)item == (Object)null)
			{
				continue;
			}
			float num3;
			try
			{
				num3 = Vector3.Distance(((Component)item).transform.position, pos);
			}
			catch
			{
				continue;
			}
			if (BrainDead(item))
			{
				if (num3 < num2)
				{
					num2 = num3;
					val2 = item;
				}
			}
			else if (num3 < num)
			{
				num = num3;
				val = item;
			}
		}
		if ((Object)(object)val != (Object)null)
		{
			LivingTarget livingTarget = Build(val);
			if (livingTarget != null && !capturedRoots.Contains(livingTarget.RootId))
			{
				return livingTarget;
			}
		}
		if (type == BubbleType.Healing && (Object)(object)val2 != (Object)null)
		{
			LivingTarget livingTarget2 = Build(val2);
			if (livingTarget2 != null && !capturedRoots.Contains(livingTarget2.RootId))
			{
				return livingTarget2;
			}
		}
		return null;
	}

	public static LivingTarget TargetFromCollider(Collider c)
	{
		if ((Object)(object)c == (Object)null || !CaptureAuthority())
		{
			return null;
		}
		try
		{
			if (IsPlayerPart(((Component)c).transform))
			{
				return null;
			}
			MarrowBody componentInParent = ((Component)c).GetComponentInParent<MarrowBody>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return null;
			}
			MarrowEntity entity = componentInParent.Entity;
			GameObject val = (((Object)(object)entity != (Object)null) ? ((Component)entity).gameObject : ((Component)((Component)componentInParent).transform.root).gameObject);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			if (capturedRoots.Contains(((Object)val).GetInstanceID()))
			{
				return null;
			}
			string name = ((Object)val).name;
			if (name.Contains("BubbleProjectile") || name.Contains("BubbleGun"))
			{
				return null;
			}
			foreach (GunManager item in GunManager.Active)
			{
				if (!item.Dead && (Object)(object)item.Root == (Object)(object)val)
				{
					return null;
				}
			}
			if (IsHeldByPlayer(val))
			{
				return null;
			}
			AIBrain componentInChildren = val.GetComponentInChildren<AIBrain>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				LivingTarget livingTarget = Build(componentInChildren);
				return (livingTarget != null && !capturedRoots.Contains(livingTarget.RootId)) ? livingTarget : null;
			}
			LivingTarget livingTarget2 = FillBodies(new LivingTarget
			{
				Kind = TargetKind.Item,
				Brain = null,
				Root = val,
				RootId = ((Object)val).GetInstanceID()
			});
			if (livingTarget2 != null && EnclosingRadius(livingTarget2) < 2.2f)
			{
				return livingTarget2;
			}
		}
		catch
		{
		}
		return null;
	}

	public static LivingTarget PlayerDeepInside(Vector3 center, float radius, Vector3 spawnPos)
	{
		//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_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)
		if (!Tuning.CapturePlayer)
		{
			return null;
		}
		Transform val = PlayerHead();
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		if (Vector3.Distance(val.position, center) > radius + 0.45f)
		{
			return null;
		}
		if (Vector3.Distance(val.position, spawnPos) < 1f)
		{
			return null;
		}
		LivingTarget livingTarget = BuildPlayer();
		if (livingTarget == null || capturedRoots.Contains(livingTarget.RootId))
		{
			return null;
		}
		float num = HealthFrac(livingTarget);
		if (!(num >= 0f) || !(num < 0.98f))
		{
			return null;
		}
		return livingTarget;
	}

	public static bool IsValid(LivingTarget t)
	{
		if (t != null)
		{
			return (Object)(object)t.Root != (Object)null;
		}
		return false;
	}

	public static Vector3 Center(LivingTarget t)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: 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)
		if (!IsValid(t))
		{
			return Vector3.zero;
		}
		Bounds val = BodyBounds(t);
		return ((Bounds)(ref val)).center;
	}

	public static float EnclosingRadius(LivingTarget t)
	{
		//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_0009: 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)
		Bounds val = BodyBounds(t);
		Vector3 extents = ((Bounds)(ref val)).extents;
		return ((Vector3)(ref extents)).magnitude;
	}

	private static Bounds BodyBounds(LivingTarget t)
	{
		//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_001c: 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_0075: 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_006d: Unknown result type (might be due to invalid IL or missing references)
		Bounds bounds = default(Bounds);
		((Bounds)(ref bounds))..ctor(t.Root.transform.position, Vector3.one * 0.2f);
		bool flag = false;
		foreach (Collider collider in t.Colliders)
		{
			if (!((Object)(object)collider == (Object)null) && !collider.isTrigger && collider.enabled && ((Component)collider).gameObject.activeInHierarchy)
			{
				if (!flag)
				{
					bounds = collider.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(collider.bounds);
				}
			}
		}
		return bounds;
	}

	public static bool Owns(LivingTarget t, Rigidbody rb)
	{
		if (!IsValid(t) || (Object)(object)rb == (Object)null)
		{
			return false;
		}
		foreach (Rigidbody body in t.Bodies)
		{
			if ((Object)(object)body == (Object)(object)rb)
			{
				return true;
			}
		}
		return false;
	}

	public static IEnumerable<Collider> AllColliders(LivingTarget t)
	{
		IEnumerable<Collider> colliders = t.Colliders;
		return colliders ?? new List<Collider>();
	}

	public static void IgnoreCollisionsWith(GameObject bubbleRoot, GameObject otherRoot, bool ignore = true)
	{
		if ((Object)(object)bubbleRoot == (Object)null || (Object)(object)otherRoot == (Object)null)
		{
			return;
		}
		try
		{
			Il2CppArrayBase<Collider> componentsInChildren = bubbleRoot.GetComponentsInChildren<Collider>(true);
			Il2CppArrayBase<Collider> componentsInChildren2 = otherRoot.GetComponentsInChildren<Collider>(true);
			foreach (Collider item in componentsInChildren)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				foreach (Collider item2 in componentsInChildren2)
				{
					if ((Object)(object)item2 != (Object)null)
					{
						Physics.IgnoreCollision(item, item2, ignore);
					}
				}
			}
		}
		catch
		{
		}
	}

	public static void IgnoreHeldItems(GameObject bubblePart)
	{
		try
		{
			Hand[] array = (Hand[])(object)new Hand[2]
			{
				Player.LeftHand,
				Player.RightHand
			};
			foreach (Hand val in array)
			{
				GameObject val2 = (((Object)(object)val != (Object)null) ? val.m_CurrentAttachedGO : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					MarrowBody componentInParent = val2.GetComponentInParent<MarrowBody>();
					GameObject otherRoot = (((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.Entity != (Object)null) ? ((Component)componentInParent.Entity).gameObject : val2);
					IgnoreCollisionsWith(bubblePart, otherRoot);
				}
			}
		}
		catch
		{
		}
	}

	public static bool PlayerIsHurt()
	{
		LivingTarget livingTarget = BuildPlayer();
		if (livingTarget == null)
		{
			return false;
		}
		float num = HealthFrac(livingTarget);
		if (num >= 0f)
		{
			return num < 0.98f;
		}
		return false;
	}

	public static GameObject PlayerRoot()
	{
		try
		{
			PhysicsRig physicsRig = Player.PhysicsRig;
			return (physicsRig != null) ? ((Component)physicsRig).gameObject : null;
		}
		catch
		{
			return null;
		}
	}

	public static void SetCaptured(LivingTarget t, bool captured)
	{
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		if (!IsValid(t))
		{
			return;
		}
		if (captured)
		{
			capturedRoots.Add(t.RootId);
			t.HadGravity = new bool[t.Bodies.Count];
			for (int i = 0; i < t.Bodies.Count; i++)
			{
				Rigidbody val = t.Bodies[i];
				if (!((Object)(object)val == (Object)null))
				{
					t.HadGravity[i] = val.useGravity;
					val.useGravity = false;
				}
			}
			if (t.IsPlayer)
			{
				t.Root.SendMessageUpwards("RagdollRig", (SendMessageOptions)1);
			}
			else if (t.Kind == TargetKind.Npc && (Object)(object)t.Brain != (Object)null && (Object)(object)t.Brain.behaviour != (Object)null)
			{
				BehaviourBaseNav behaviour = t.Brain.behaviour;
				t.SavedNavState = ExtractNavState(behaviour);
				JsonUtility.FromJsonOverwrite("{\"locoState\":5, \"mentalState\":0}", (Object)(object)behaviour);
			}
			return;
		}
		capturedRoots.Remove(t.RootId);
		for (int j = 0; j < t.Bodies.Count; j++)
		{
			Rigidbody val2 = t.Bodies[j];
			if (!((Object)(object)val2 == (Object)null))
			{
				if (t.HadGravity != null && j < t.HadGravity.Length)
				{
					val2.useGravity = t.HadGravity[j];
				}
				val2.velocity = Vector3.zero;
				val2.angularVelocity = Vector3.zero;
			}
		}
		if (t.IsPlayer)
		{
			t.Root.SendMessageUpwards("UnRagdollRig", (SendMessageOptions)1);
		}
		else if (t.Kind == TargetKind.Npc && (Object)(object)t.Brain != (Object)null && (Object)(object)t.Brain.behaviour != (Object)null && !IsDead(t) && t.SavedNavState != null)
		{
			JsonUtility.FromJsonOverwrite(t.SavedNavState, (Object)(object)t.Brain.behaviour);
		}
	}

	public static void ReassertHold(LivingTarget t)
	{
		if (!IsValid(t) || !t.IsPlayer)
		{
			return;
		}
		try
		{
			t.Root.SendMessageUpwards("RagdollRig", (SendMessageOptions)1);
		}
		catch
		{
		}
	}

	public static float PlayerHeight()
	{
		return AvatarHeight(null);
	}

	public static float AvatarHeight(RigManager rig)
	{
		//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_0084: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Avatar val = (((Object)(object)rig != (Object)null) ? rig.avatar : Player.Avatar);
			if ((Object)(object)val == (Object)null)
			{
				val = Player.Avatar;
			}
			if ((Object)(object)val == (Object)null)
			{
				return 1.8f;
			}
			float num = float.MaxValue;
			float num2 = float.MinValue;
			bool flag = false;
			foreach (Renderer componentsInChild in ((Component)val).GetComponentsInChildren<Renderer>(false))
			{
				if (!((Object)(object)componentsInChild == (Object)null))
				{
					Bounds bounds = componentsInChild.bounds;
					num = Mathf.Min(num, ((Bounds)(ref bounds)).center.y - ((Bounds)(ref bounds)).extents.y);
					num2 = Mathf.Max(num2, ((Bounds)(ref bounds)).center.y + ((Bounds)(ref bounds)).extents.y);
					flag = true;
				}
			}
			return flag ? Mathf.Clamp(num2 - num, 0.6f, 3f) : 1.8f;
		}
		catch
		{
			return 1.8f;
		}
	}

	private static string ExtractNavState(BehaviourBaseNav nav)
	{
		try
		{
			string input = JsonUtility.ToJson((Object)(object)nav);
			Match match = Regex.Match(input, "\"locoState\"\\s*:\\s*(-?\\d+)");
			Match match2 = Regex.Match(input, "\"mentalState\"\\s*:\\s*(-?\\d+)");
			if (match.Success && match2.Success)
			{
				return "{\"locoState\":" + match.Groups[1].Value + ", \"mentalState\":" + match2.Groups[1].Value + "}";
			}
		}
		catch
		{
		}
		return "{\"locoState\":1, \"mentalState\":2}";
	}

	public static void HoldStep(LivingTarget t, float dt, Vector3 holdCenter, float radius, bool limp)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_007d: 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_00a8: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: 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_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: 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_00e6: 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_00f6: 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_00d0: 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)
		if (!IsValid(t))
		{
			return;
		}
		Vector3 val = Center(t);
		float num = (t.IsPlayer ? 4f : 6f);
		float num2 = (t.IsPlayer ? 5f : 8f);
		float num3 = 1f - Mathf.Exp(-10f * dt);
		foreach (Rigidbody body in t.Bodies)
		{
			if (!((Object)(object)body == (Object)null))
			{
				Vector3 val2 = body.worldCenterOfMass - val;
				float num4 = radius * 0.8f;
				if (((Vector3)(ref val2)).magnitude > num4)
				{
					val2 = ((Vector3)(ref val2)).normalized * num4;
				}
				Vector3 val3 = (holdCenter + val2 - body.worldCenterOfMass) * num;
				if (((Vector3)(ref val3)).magnitude > num2)
				{
					val3 = ((Vector3)(ref val3)).normalized * num2;
				}
				body.velocity = Vector3.Lerp(body.velocity, val3, num3);
				body.angularVelocity *= Mathf.Exp(-2f * dt);
			}
		}
	}

	public static void Damage(LivingTarget t, float hp)
	{
		//IL_0068: 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_0079: Expected O, but got Unknown
		if (!IsValid(t))
		{
			return;
		}
		try
		{
			if (t.IsPlayer)
			{
				RigManager rigManager = Player.RigManager;
				Health val = ((rigManager != null) ? rigManager.health : null);
				if ((Object)(object)val != (Object)null)
				{
					val.TAKEDAMAGE(hp);
				}
			}
			else if ((Object)(object)t.Brain != (Object)null && FusionGate.IsAuthority)
			{
				BehaviourBaseNav behaviour = t.Brain.behaviour;
				SubBehaviourHealth val2 = ((behaviour != null) ? behaviour.health : null);
				if (val2 != null)
				{
					val2.TakeDamage(1, new Attack
					{
						damage = hp
					});
				}
			}
		}
		catch (Exception ex)
		{
			MelonLogger.Warning("Damage failed: " + ex.Message);
		}
	}

	public static void Heal(LivingTarget t, float hp)
	{
		Damage(t, 0f - hp);
	}

	public static bool Revive(LivingTarget t)
	{
		if (!IsValid(t) || (Object)(object)t.Brain == (Object)null)
		{
			return false;
		}
		if (t.Kind != TargetKind.Corpse && !IsDead(t))
		{
			return false;
		}
		if (!FusionGate.IsAuthority)
		{
			return false;
		}
		try
		{
			t.Brain.OnResurrection();
			deadBrains.Remove(((Object)t.Brain).GetInstanceID());
			t.Kind = TargetKind.Npc;
			Heal(t, 50f);
			if ((Object)(object)t.Brain.behaviour != (Object)null)
			{
				JsonUtility.FromJsonOverwrite("{\"locoState\":5, \"mentalState\":0}", (Object)(object)t.Brain.behaviour);
			}
			t.SavedNavState = "{\"locoState\":1, \"mentalState\":2}";
			return true;
		}
		catch (Exception ex)
		{
			MelonLogger.Warning("Revive failed: " + ex.Message);
			return false;
		}
	}

	public static float HealthFrac(LivingTarget t)
	{
		try
		{
			object obj;
			if (!t.IsPlayer)
			{
				AIBrain brain = t.Brain;
				if (brain == null)
				{
					obj = null;
				}
				else
				{
					BehaviourBaseNav behaviour = brain.behaviour;
					obj = ((behaviour != null) ? behaviour.health : null);
				}
			}
			else
			{
				RigManager rigManager = Player.RigManager;
				obj = ((rigManager != null) ? rigManager.health : null);
			}
			object obj2 = obj;
			if (obj2 == null)
			{
				return -1f;
			}
			float num = ReadFloat(obj2, "curr_Health", "cur_hp", "curr_health");
			float num2 = ReadFloat(obj2, "max_Health", "max_hp", "max_health");
			if (num >= 0f && num2 > 0f)
			{
				return num / num2;
			}
		}
		catch
		{
		}
		return -1f;
	}

	private static float ReadFloat(object obj, params string[] names)
	{
		if (!TryReadFloat(obj, out var val, names))
		{
			return -1f;
		}
		return val;
	}

	private static bool TryReadFloat(object obj, out float val, params string[] names)
	{
		val = -1f;
		Type type = obj.GetType();
		foreach (string name in names)
		{
			PropertyInfo property = type.GetProperty(name);
			if (property != null && property.PropertyType == typeof(float))
			{
				val = (float)property.GetValue(obj);
				return true;
			}
			FieldInfo field = type.GetField(name);
			if (field != null && field.FieldType == typeof(float))
			{
				val = (float)field.GetValue(obj);
				return true;
			}
		}
		return false;
	}

	public static bool IsDead(LivingTarget t)
	{
		if (!IsValid(t))
		{
			return true;
		}
		if (t.Kind == TargetKind.Player || t.Kind == TargetKind.Item)
		{
			return false;
		}
		if (!((Object)(object)t.Brain == (Object)null))
		{
			return BrainDead(t.Brain);
		}
		return true;
	}

	public static List<RigManager> AllRigs()
	{
		if (Time.time - rigCacheAt > 3f)
		{
			rigCache.Clear();
			try
			{
				Il2CppArrayBase<RigManager> val = Object.FindObjectsOfType<RigManager>();
				if (val != null)
				{
					foreach (RigManager item in val)
					{
						if ((Object)(object)item != (Object)null)
						{
							rigCache.Add(item);
						}
					}
				}
			}
			catch
			{
			}
			rigCacheAt = Time.time;
		}
		return rigCache;
	}

	public static Vector3 RigHeadPos(RigManager rig)
	{
		//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_003f: 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_001d: 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_004a: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			PhysicsRig physicsRig = rig.physicsRig;
			Transform val = ((physicsRig != null) ? ((Rig)physicsRig).m_head : null);
			if ((Object)(object)val != (Object)null)
			{
				return val.position;
			}
		}
		catch
		{
		}
		return ((Component)rig).transform.position + Vector3.up * 1.5f;
	}

	public static RigManager NearestRig(Vector3 pos, float maxDist)
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		RigManager result = null;
		float num = maxDist;
		foreach (RigManager item in AllRigs())
		{
			if (!((Object)(object)item == (Object)null))
			{
				float num2;
				try
				{
					num2 = Vector3.Distance(((Component)item).transform.position, pos);
				}
				catch
				{
					continue;
				}
				if (num2 < num)
				{
					num = num2;
					result = item;
				}
			}
		}
		return result;
	}

	private static void SetRigCloaked(RigManager rig, bool cloaked)
	{
		if ((Object)(object)rig == (Object)null)
		{
			return;
		}
		int instanceID = ((Object)rig).GetInstanceID();
		try
		{
			if (cloaked)
			{
				if (cloakedRenderers.ContainsKey(instanceID))
				{
					return;
				}
				List<Renderer> list = new List<Renderer>();
				foreach (Renderer componentsInChild in ((Component)rig).GetComponentsInChildren<Renderer>(false))
				{
					if (!((Object)(object)componentsInChild == (Object)null) && componentsInChild.enabled)
					{
						componentsInChild.enabled = false;
						list.Add(componentsInChild);
					}
				}
				cloakedRenderers[instanceID] = list;
			}
			else
			{
				if (!cloakedRenderers.TryGetValue(instanceID, out var value))
				{
					return;
				}
				cloakedRenderers.Remove(instanceID);
				{
					foreach (Renderer item in value)
					{
						if ((Object)(object)item != (Object)null)
						{
							item.enabled = true;
						}
					}
					return;
				}
			}
		}
		catch
		{
		}
	}

	public static void CloakRigsInside(Vector3 center, float radius, List<RigManager> cloaked)
	{
		//IL_0035: 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)
		RigManager val = null;
		try
		{
			val = Player.RigManager;
		}
		catch
		{
		}
		foreach (RigManager item in AllRigs())
		{
			if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)val))
			{
				bool flag = Vector3.Distance(RigHeadPos(item), center) <= radius + 0.15f;
				bool flag2 = cloaked.Contains(item);
				if (flag && !flag2)
				{
					SetRigCloaked(item, cloaked: true);
					cloaked.Add(item);
				}
				else if (!flag && flag2)
				{
					SetRigCloaked(item, cloaked: false);
					cloaked.Remove(item);
				}
			}
		}
	}

	public static void UncloakAll(List<RigManager> cloaked)
	{
		foreach (RigManager item in cloaked)
		{
			if ((Object)(object)item != (Object)null)
			{
				SetRigCloaked(item, cloaked: false);
			}
		}
		cloaked.Clear();
	}

	public static float TotalMass(LivingTarget t)
	{
		if (!IsValid(t))
		{
			return 1f;
		}
		float num = 0f;
		foreach (Rigidbody body in t.Bodies)
		{
			if (!((Object)(object)body == (Object)null))
			{
				try
				{
					num += body.mass;
				}
				catch
				{
				}
			}
		}
		return Mathf.Max(0.05f, num);
	}

	public static Transform PlayerHead()
	{
		try
		{
			return Player.Head;
		}
		catch
		{
			return null;
		}
	}

	public static bool PlayerHeadInside(Vector3 center, float radius)
	{
		//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)
		Transform val = PlayerHead();
		if ((Object)(object)val != (Object)null)
		{
			return Vector3.Distance(val.position, center) <= radius;
		}
		return false;
	}

	public static float PlayerHeadDistance(Vector3 center)
	{
		//IL_0016: 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)
		Transform val = PlayerHead();
		if (!((Object)(object)val != (Object)null))
		{
			return 999f;
		}
		return Vector3.Distance(val.position, center);
	}

	public static LivingTarget PlayerIfNear(Vector3 center, float range)
	{
		//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)
		Transform val = PlayerHead();
		if ((Object)(object)val == (Object)null || Vector3.Distance(val.position, center) > range)
		{
			return null;
		}
		LivingTarget livingTarget = BuildPlayer();
		if (livingTarget == null || capturedRoots.Contains(livingTarget.RootId))
		{
			return null;
		}
		return livingTarget;
	}

	public static bool ConsumePlayerStruggle()
	{
		bool result = struggleLatch;
		struggleLatch = false;
		return result;
	}

	public static void PumpStruggleInput()
	{
		try
		{
			Hand leftHand = Player.LeftHand;
			Hand rightHand = Player.RightHand;
			int num;
			if (!((Object)(object)leftHand != (Object)null) || !leftHand._indexButtonDown)
			{
				if ((Object)(object)rightHand != (Object)null)
				{
					num = (rightHand._indexButtonDown ? 1 : 0);
					if (num != 0)
					{
						goto IL_0035;
					}
				}
				else
				{
					num = 0;
				}
				goto IL_0042;
			}
			num = 1;
			goto IL_0035;
			IL_0042:
			triggerWasDown = (byte)num != 0;
			return;
			IL_0035:
			if (!triggerWasDown)
			{
				struggleLatch = true;
			}
			goto IL_0042;
		}
		catch
		{
		}
	}

	public static Hand HoldingHand(GameObject root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return null;
		}
		try
		{
			Hand leftHand = Player.LeftHand;
			Hand rightHand = Player.RightHand;
			if (IsHeldBy(leftHand, root))
			{
				return leftHand;
			}
			if (IsHeldBy(rightHand, root))
			{
				return rightHand;
			}
		}
		catch
		{
		}
		return null;
	}

	private static bool IsHeldBy(Hand hand, GameObject root)
	{
		if ((Object)(object)hand == (Object)null)
		{
			return false;
		}
		GameObject currentAttachedGO = hand.m_CurrentAttachedGO;
		if ((Object)(object)currentAttachedGO == (Object)null)
		{
			return false;
		}
		Transform val = currentAttachedGO.transform;
		while ((Object)(object)val != (Object)null)
		{
			if ((Object)(object)((Component)val).gameObject == (Object)(object)root)
			{
				return true;
			}
			val = val.parent;
		}
		return false;
	}

	public static GameObject SpawnCaste