Decompiled source of Spectator plus v2.9.1

SpectateEnemy.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Overlay;
using SpectateEnemy.UI;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SpectateEnemy")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("My first plugin")]
[assembly: AssemblyFileVersion("2.8.0.0")]
[assembly: AssemblyInformationalVersion("2.8.0")]
[assembly: AssemblyProduct("SpectateEnemy")]
[assembly: AssemblyTitle("SpectateEnemy")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.8.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SpectateEnemy
{
	internal static class Doorways
	{
		internal const float Reach = 5f;

		private const float AimDot = 0.85f;

		private const float MarkerSize = 18f;

		private static EntranceTeleport[] doors;

		private static float nextScan;

		private static bool useHeld;

		internal static EntranceTeleport Aimed { get; private set; }

		internal static void Forget()
		{
			doors = null;
			nextScan = 0f;
			useHeld = false;
			Aimed = null;
		}

		internal static void Tick()
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			Camera val = ActiveCamera();
			if ((Object)(object)val == (Object)null)
			{
				Forget();
				return;
			}
			if (Time.time >= nextScan)
			{
				nextScan = Time.time + 2f;
				doors = Object.FindObjectsByType<EntranceTeleport>((FindObjectsSortMode)0);
			}
			Aimed = AimedAt(val);
			PlayerControllerB val2 = Local();
			if ((Object)(object)val2 == (Object)null || val2.playerActions == null || SpectateEnemies.Instance.IsMenuOpen())
			{
				useHeld = false;
				return;
			}
			MovementActions movement = val2.playerActions.Movement;
			bool flag = ((MovementActions)(ref movement)).Interact.IsPressed();
			bool flag2 = flag && !useHeld;
			useHeld = flag;
			if (flag2 && (Object)(object)Aimed != (Object)null)
			{
				Use(Aimed);
			}
		}

		private static void Use(EntranceTeleport door)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			SpectateEnemies instance = SpectateEnemies.Instance;
			door.TeleportPlayer();
			if (instance.Mode == SpectateMode.Ghost)
			{
				GhostBody.Settle();
				return;
			}
			if ((Object)(object)door.exitScript != (Object)null && (Object)(object)door.exitScript.entrancePoint != (Object)null)
			{
				instance.SetFreeCamPosition(door.exitScript.entrancePoint.position);
			}
			Aimed = null;
		}

		private static EntranceTeleport AimedAt(Camera camera)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (doors == null)
			{
				return null;
			}
			Vector3 position = ((Component)camera).transform.position;
			Vector3 forward = ((Component)camera).transform.forward;
			EntranceTeleport result = null;
			float num = 0.85f;
			EntranceTeleport[] array = doors;
			foreach (EntranceTeleport val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Vector3 val2 = PointOf(val) - position;
				if (!(((Vector3)(ref val2)).sqrMagnitude > 25f))
				{
					float num2 = Vector3.Dot(forward, ((Vector3)(ref val2)).normalized);
					if (num2 > num)
					{
						num = num2;
						result = val;
					}
				}
			}
			return result;
		}

		internal static Vector3 PointOf(EntranceTeleport door)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			return ((Object)(object)door.entrancePoint != (Object)null) ? door.entrancePoint.position : ((Component)door).transform.position;
		}

		internal static string NameOf(EntranceTeleport door)
		{
			if (door.entranceId != 0)
			{
				return "FIRE EXIT";
			}
			return door.isEntranceToBuilding ? "ENTRANCE" : "EXIT";
		}

		internal static Camera ActiveCamera()
		{
			if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
			{
				return null;
			}
			SpectateEnemies instance = SpectateEnemies.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			if (instance.Mode == SpectateMode.Ghost)
			{
				PlayerControllerB val = Local();
				return ((Object)(object)val == (Object)null) ? null : val.gameplayCamera;
			}
			return (instance.Mode == SpectateMode.FreeCam) ? StartOfRound.Instance.spectateCamera : null;
		}

		internal static void DrawMarkers()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Expected O, but got Unknown
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: 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_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			Camera val = ActiveCamera();
			if ((Object)(object)val == (Object)null || doors == null)
			{
				return;
			}
			Color color = GUI.color;
			GUI.color = OverlayStyles.Primary;
			Vector3 position = ((Component)val).transform.position;
			EntranceTeleport[] array = doors;
			Rect val5 = default(Rect);
			foreach (EntranceTeleport val2 in array)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					Vector3 val3 = PointOf(val2);
					Vector3 val4 = val.WorldToScreenPoint(val3);
					if (!(val4.z <= 0f))
					{
						float x = val4.x;
						float num = (float)Screen.height - val4.y;
						bool flag = (Object)(object)val2 == (Object)(object)Aimed;
						float num2 = 9f;
						float num3 = (flag ? 3f : 1f);
						((Rect)(ref val5))..ctor(x - num2, num - num2, 18f, 18f);
						OverlayStyles.Fill(new Rect(((Rect)(ref val5)).x, ((Rect)(ref val5)).y, ((Rect)(ref val5)).width, num3), OverlayStyles.Primary);
						OverlayStyles.Fill(new Rect(((Rect)(ref val5)).x, ((Rect)(ref val5)).yMax - num3, ((Rect)(ref val5)).width, num3), OverlayStyles.Primary);
						OverlayStyles.Fill(new Rect(((Rect)(ref val5)).x, ((Rect)(ref val5)).y, num3, ((Rect)(ref val5)).height), OverlayStyles.Primary);
						OverlayStyles.Fill(new Rect(((Rect)(ref val5)).xMax - num3, ((Rect)(ref val5)).y, num3, ((Rect)(ref val5)).height), OverlayStyles.Primary);
						string text = $"{NameOf(val2)}  {Vector3.Distance(position, val3):F0}m";
						GUIContent val6 = new GUIContent(text);
						Vector2 val7 = OverlayStyles.Label.CalcSize(val6);
						GUI.Label(new Rect(x - val7.x / 2f, ((Rect)(ref val5)).yMax + 2f, val7.x, val7.y), val6, flag ? OverlayStyles.LabelStrong : OverlayStyles.Label);
					}
				}
			}
			GUI.color = color;
		}

		private static PlayerControllerB Local()
		{
			return ((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController;
		}
	}
	internal static class GhostBody
	{
		private const int FloorLayer = 2;

		private const float FloorThickness = 4f;

		private const float FloorWidth = 6f;

		private const float ProbeAbove = 1.2f;

		private const float ProbeBelow = 4f;

		private const float DoubleTapWindow = 0.35f;

		private const float FlySprintMultiplier = 2.5f;

		internal static float FlySpeed = 9f;

		private static readonly FieldRef<PlayerControllerB, bool> CameraDisabled = AccessTools.FieldRefAccess<PlayerControllerB, bool>("isCameraDisabled");

		private static GameObject floor;

		private static BoxCollider floorBox;

		private static LayerMask savedExcludeLayers;

		private static bool savedDeadPosition;

		private static float savedMovementSpeed;

		private static bool savedTestingPlayer;

		private static int savedLayer;

		private static bool jumpHeld;

		private static float lastJumpTime;

		private static float flyHeight;

		internal static bool Active { get; private set; }

		internal static bool Flying { get; private set; }

		internal static bool NoClip { get; private set; }

		private static PlayerControllerB Local()
		{
			return ((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController;
		}

		internal static bool Enter(Vector3 at)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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)
			PlayerControllerB val = Local();
			if (Active || (Object)(object)val == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)HUDManager.Instance == (Object)null)
			{
				return false;
			}
			Active = true;
			Flying = false;
			NoClip = false;
			jumpHeld = false;
			lastJumpTime = 0f;
			EnsureFloor(val);
			savedDeadPosition = val.setPositionOfDeadPlayer;
			savedExcludeLayers = ((Collider)val.thisController).excludeLayers;
			savedMovementSpeed = val.movementSpeed;
			savedTestingPlayer = val.isTestingPlayer;
			savedLayer = ((Component)val).gameObject.layer;
			val.isTestingPlayer = true;
			((Component)val).gameObject.layer = 2;
			val.setPositionOfDeadPlayer = false;
			val.isClimbingLadder = false;
			val.inSpecialInteractAnimation = false;
			val.disableMoveInput = false;
			val.disableLookInput = false;
			val.disableInteract = true;
			val.ResetZAndXRotation();
			((Collider)val.thisController).enabled = true;
			ApplyCollision(val);
			val.TeleportPlayer(GroundUnder(at), false, 0f, false, true);
			val.DisablePlayerModel(((Component)val).gameObject, true, true);
			val.Crouch(false);
			CameraDisabled.Invoke(val) = true;
			HUDManager.Instance.HideHUD(false);
			HUDManager.Instance.SetNearDepthOfFieldEnabled(false);
			PlaceFloor(val);
			return true;
		}

		internal static void Exit()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if (!Active)
			{
				return;
			}
			Active = false;
			Flying = false;
			NoClip = false;
			DestroyFloor();
			PlayerControllerB val = Local();
			if (!((Object)(object)val == (Object)null))
			{
				val.isTestingPlayer = savedTestingPlayer;
				((Component)val).gameObject.layer = savedLayer;
				val.setPositionOfDeadPlayer = savedDeadPosition;
				val.disableInteract = false;
				((Collider)val.thisController).excludeLayers = savedExcludeLayers;
				val.movementSpeed = savedMovementSpeed;
				val.DisablePlayerModel(((Component)val).gameObject, false, false);
				((Renderer)val.thisPlayerModelArms).enabled = false;
				val.hasBegunSpectating = false;
				if ((Object)(object)StartOfRound.Instance != (Object)null)
				{
					StartOfRound.Instance.SwitchCamera(StartOfRound.Instance.spectateCamera);
					val.ChangeAudioListenerToObject(((Component)StartOfRound.Instance.spectateCamera).gameObject);
				}
				if ((Object)(object)HUDManager.Instance != (Object)null)
				{
					HUDManager.Instance.HideHUD(true);
				}
			}
		}

		internal static bool Warp(Vector3 point)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB val = Local();
			if (!Active || (Object)(object)val == (Object)null)
			{
				return false;
			}
			val.TeleportPlayer((NoClip || Flying) ? point : GroundUnder(point), false, 0f, false, true);
			flyHeight = ((Component)val).transform.position.y;
			PlaceFloor(val);
			return true;
		}

		internal static void SetNoClip(bool on)
		{
			if (Active)
			{
				NoClip = on;
				PlayerControllerB val = Local();
				if ((Object)(object)val != (Object)null)
				{
					ApplyCollision(val);
				}
			}
		}

		internal static void Settle()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB val = Local();
			if (Active && !((Object)(object)val == (Object)null))
			{
				flyHeight = ((Component)val).transform.position.y;
				PlaceFloor(val);
			}
		}

		private static void ApplyCollision(PlayerControllerB player)
		{
			//IL_0017: 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)
			((Collider)player.thisController).excludeLayers = (NoClip ? LayerMask.op_Implicit(-5) : savedExcludeLayers);
			if ((Object)(object)floorBox != (Object)null)
			{
				((Collider)floorBox).enabled = NoClip || Flying;
			}
		}

		private static Vector3 GroundUnder(Vector3 point)
		{
			//IL_0017: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0055: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)StartOfRound.Instance == (Object)null)
			{
				return point;
			}
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(point + Vector3.up * 1.2f, Vector3.down);
			RaycastHit val2 = default(RaycastHit);
			return Physics.Raycast(val, ref val2, 200f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1) ? ((RaycastHit)(ref val2)).point : point;
		}

		internal static void LateTick()
		{
			PlayerControllerB val = Local();
			if (Active && !((Object)(object)val == (Object)null))
			{
				val.sprintMeter = 1f;
				val.isExhausted = false;
				HideLivingHud();
				ReadFlightToggle(val);
				if (Flying)
				{
					Fly(val);
					return;
				}
				val.movementSpeed = savedMovementSpeed;
				PlaceFloor(val);
			}
		}

		private static void HideLivingHud()
		{
			HUDManager instance = HUDManager.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if (instance.Inventory != null && (Object)(object)instance.Inventory.canvasGroup != (Object)null)
				{
					instance.Inventory.canvasGroup.alpha = 0f;
				}
				if (instance.PlayerInfo != null && (Object)(object)instance.PlayerInfo.canvasGroup != (Object)null)
				{
					instance.PlayerInfo.canvasGroup.alpha = 0f;
				}
			}
		}

		private static void ReadFlightToggle(PlayerControllerB player)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			if (player.playerActions == null || ((Object)(object)SpectateEnemies.Instance != (Object)null && SpectateEnemies.Instance.IsMenuOpen()))
			{
				jumpHeld = false;
				return;
			}
			MovementActions movement = player.playerActions.Movement;
			bool flag = ((MovementActions)(ref movement)).Jump.IsPressed();
			bool flag2 = flag && !jumpHeld;
			jumpHeld = flag;
			if (!flag2)
			{
				return;
			}
			if (Time.time - lastJumpTime <= 0.35f)
			{
				Flying = !Flying;
				if (Flying)
				{
					player.Crouch(false);
					flyHeight = ((Component)player).transform.position.y;
				}
				ApplyCollision(player);
				lastJumpTime = 0f;
			}
			else
			{
				lastJumpTime = Time.time;
			}
		}

		private static void Fly(PlayerControllerB player)
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: 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_00a3: 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)
			player.movementSpeed = FlySpeed;
			if (player.playerActions != null && ((Object)(object)SpectateEnemies.Instance == (Object)null || !SpectateEnemies.Instance.IsMenuOpen()))
			{
				float flySpeed = FlySpeed;
				MovementActions movement = player.playerActions.Movement;
				float num = flySpeed * (((MovementActions)(ref movement)).Sprint.IsPressed() ? 2.5f : 1f);
				movement = player.playerActions.Movement;
				if (((MovementActions)(ref movement)).Jump.IsPressed())
				{
					flyHeight += num * Time.deltaTime;
				}
				movement = player.playerActions.Movement;
				if (((MovementActions)(ref movement)).Crouch.IsPressed())
				{
					flyHeight -= num * Time.deltaTime;
				}
			}
			Vector3 position = ((Component)player).transform.position;
			SetFloor(position.x, flyHeight, position.z);
			float num2 = flyHeight - position.y;
			if (Mathf.Abs(num2) > 0.001f && ((Collider)player.thisController).enabled)
			{
				player.thisController.Move(Vector3.up * num2);
			}
		}

		private static void PlaceFloor(PlayerControllerB player)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_006c: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)floor == (Object)null) && !((Object)(object)StartOfRound.Instance == (Object)null))
			{
				Vector3 position = ((Component)player).transform.position;
				Ray val = default(Ray);
				((Ray)(ref val))..ctor(position + Vector3.up * 1.2f, Vector3.down);
				RaycastHit val2 = default(RaycastHit);
				float top = (Physics.Raycast(val, ref val2, 5.2f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1) ? ((RaycastHit)(ref val2)).point.y : (position.y - 500f));
				SetFloor(position.x, top, position.z);
			}
		}

		private static void SetFloor(float x, float top, float z)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)floor != (Object)null)
			{
				floor.transform.position = new Vector3(x, top - 2f, z);
			}
		}

		private static void EnsureFloor(PlayerControllerB player)
		{
			//IL_0018: 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_002a: Expected O, but got Unknown
			//IL_004d: 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)
			if (!((Object)(object)floor != (Object)null))
			{
				floor = new GameObject("SpectateEnemiesGhostFloor")
				{
					layer = 2
				};
				floorBox = floor.AddComponent<BoxCollider>();
				floorBox.size = new Vector3(6f, 4f, 6f);
				((Collider)floorBox).excludeLayers = LayerMask.op_Implicit(-5);
				Object.DontDestroyOnLoad((Object)(object)floor);
			}
		}

		private static void DestroyFloor()
		{
			if (!((Object)(object)floor == (Object)null))
			{
				Object.Destroy((Object)(object)floor);
				floor = null;
				floorBox = null;
			}
		}
	}
	[BepInPlugin("SpectateEnemy", "SpectateEnemy", "2.9.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class Plugin : BaseUnityPlugin
	{
		public static MethodInfo raycastSpectate;

		public static MethodInfo displaySpectatorTip;

		public static ConfigFile Configuration;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			Configuration = ((BaseUnityPlugin)this).Config;
			harmony = new Harmony("SpectateEnemy");
			harmony.PatchAll();
			raycastSpectate = AccessTools.Method(typeof(PlayerControllerB), "RaycastSpectateCameraAroundPivot", (Type[])null, (Type[])null);
			displaySpectatorTip = AccessTools.Method(typeof(HUDManager), "DisplaySpectatorTip", (Type[])null, (Type[])null);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"SpectateEnemy loaded!");
		}
	}
	internal static class RenderView
	{
		internal const float MaxBrightness = 5f;

		internal static ConfigEntry<float> Brightness;

		internal static ConfigEntry<bool> FogOff;

		private static readonly Type FogType = AccessTools.TypeByName("UnityEngine.Rendering.HighDefinition.LocalVolumetricFog");

		private static readonly List<Behaviour> silenced = new List<Behaviour>();

		private static Light light;

		private static Component lightData;

		private static MethodInfo setIntensity;

		private static float baseIntensity;

		private static float nextFogScan;

		private static bool applied;

		internal static void Init()
		{
			Brightness = Plugin.Configuration.Bind<float>("Render", "Brightness", 0f, "How bright the world is while you are dead, inside and out. 0 leaves it as the game lit it; 1 is about what the night vision in the facility gives you. Kept between deaths.");
			FogOff = Plugin.Configuration.Bind<bool>("Render", "Disable Fog", false, "Takes the volumetric fog out while you are dead - the weather's and the facility's both. Kept between deaths.");
		}

		internal static string Summary()
		{
			bool flag = Brightness.Value > 0.01f;
			if (flag && FogOff.Value)
			{
				return $"{Brightness.Value:0.##}x, no fog";
			}
			if (FogOff.Value)
			{
				return "no fog";
			}
			return flag ? $"{Brightness.Value:0.##}x" : "as it comes";
		}

		internal static void Tick(Vector3 viewpoint)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			applied = true;
			ApplyLight(viewpoint);
			ApplyFog();
		}

		internal static void Restore()
		{
			if (applied)
			{
				applied = false;
				if ((Object)(object)light != (Object)null)
				{
					((Behaviour)light).enabled = false;
				}
				ReleaseFog();
			}
		}

		private static void ApplyLight(Vector3 viewpoint)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(Brightness.Value, 0f, 5f);
			if (num <= 0.01f)
			{
				if ((Object)(object)light != (Object)null)
				{
					((Behaviour)light).enabled = false;
				}
				return;
			}
			EnsureLight();
			if ((Object)(object)light == (Object)null)
			{
				return;
			}
			((Component)light).transform.position = viewpoint;
			((Behaviour)light).enabled = true;
			float num2 = baseIntensity * num;
			light.intensity = num2;
			if (setIntensity == null || (Object)(object)lightData == (Object)null)
			{
				return;
			}
			try
			{
				setIntensity.Invoke(lightData, new object[1] { num2 });
			}
			catch (Exception)
			{
				setIntensity = null;
			}
		}

		private static void EnsureLight()
		{
			if ((Object)(object)light != (Object)null)
			{
				return;
			}
			PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController);
			if ((Object)(object)val == (Object)null || (Object)(object)val.nightVision == (Object)null)
			{
				return;
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)val.nightVision).gameObject);
			((Object)val2).name = "SpectateEnemiesViewLight";
			val2.transform.SetParent((Transform)null, true);
			Object.DontDestroyOnLoad((Object)(object)val2);
			light = val2.GetComponent<Light>();
			if ((Object)(object)light == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return;
			}
			light.shadows = (LightShadows)0;
			((Behaviour)light).enabled = false;
			baseIntensity = Mathf.Max(light.intensity, 1f);
			Type type = AccessTools.TypeByName("UnityEngine.Rendering.HighDefinition.HDAdditionalLightData");
			if (!(type == null))
			{
				lightData = val2.GetComponent(type);
				if ((Object)(object)lightData != (Object)null)
				{
					setIntensity = AccessTools.Method(type, "SetIntensity", new Type[1] { typeof(float) }, (Type[])null);
				}
			}
		}

		private static void ApplyFog()
		{
			if (FogType == null)
			{
				return;
			}
			if (!FogOff.Value)
			{
				ReleaseFog();
			}
			else
			{
				if (Time.time < nextFogScan)
				{
					return;
				}
				nextFogScan = Time.time + 2f;
				Object[] array = Object.FindObjectsByType(FogType, (FindObjectsSortMode)0);
				foreach (Object val in array)
				{
					Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
					if (val2 != null && val2.enabled)
					{
						val2.enabled = false;
						silenced.Add(val2);
					}
				}
			}
		}

		private static void ReleaseFog()
		{
			nextFogScan = 0f;
			if (silenced.Count == 0)
			{
				return;
			}
			foreach (Behaviour item in silenced)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.enabled = true;
				}
			}
			silenced.Clear();
		}
	}
	internal class Spectatable : MonoBehaviour
	{
		public SpectatableType type = SpectatableType.Enemy;

		public string enemyName = "Enemy";

		public string maskedName = string.Empty;

		public EnemyAI enemyInstance = null;
	}
	internal enum SpectatableType
	{
		Enemy,
		Masked,
		GhostGirl
	}
	internal enum SpectateMode
	{
		Spectate,
		FreeCam,
		Ghost
	}
	internal class SpectateEnemies : MonoBehaviour
	{
		public static SpectateEnemies Instance;

		public int SpectatedEnemyIndex = -1;

		public bool SpectatingEnemies = false;

		public Spectatable[] SpectatorList;

		public float ZoomLevel = 1f;

		public ConfigEntry<bool> HideControls;

		public SpectateMode Mode = SpectateMode.Spectate;

		public float FreeCamSpeed = 8f;

		private Vector3 camPosition;

		private float camYaw;

		private float camPitch;

		private Transform anchor;

		private string anchorName = string.Empty;

		private float lastScroll;

		internal bool LightOn
		{
			get
			{
				Light val = CurrentLight();
				return (Object)(object)val != (Object)null && ((Behaviour)val).enabled;
			}
		}

		internal Spectatable CurrentTarget => (SpectatingEnemies && (Object)(object)anchor == (Object)null && SpectatorList != null) ? SpectatorList.ElementAtOrDefault(SpectatedEnemyIndex) : null;

		internal Transform CurrentAnchor => SpectatingEnemies ? anchor : null;

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			HideControls = Plugin.Configuration.Bind<bool>("Config", "Hide Controls", false, "Hides the controls toolip on the right hand side.");
			RenderView.Init();
			Plugin.Configuration.SaveOnConfigSet = false;
			SpectateMenu.Register();
		}

		private static bool CanControlCamera()
		{
			if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
			{
				return false;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			return (Object)(object)localPlayerController != (Object)null && ((NetworkBehaviour)localPlayerController).IsOwner && localPlayerController.isPlayerDead && !StartOfRound.Instance.shipIsLeaving && (!((NetworkBehaviour)localPlayerController).IsServer || localPlayerController.isHostPlayerObject);
		}

		internal void ToggleLight()
		{
			Light val = CurrentLight();
			if ((Object)(object)val != (Object)null)
			{
				((Behaviour)val).enabled = !((Behaviour)val).enabled;
			}
		}

		private Light CurrentLight()
		{
			if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
			{
				return null;
			}
			if (Mode == SpectateMode.Ghost)
			{
				PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
				return ((Object)(object)localPlayerController == (Object)null) ? null : localPlayerController.helmetLight;
			}
			Camera spectateCamera = StartOfRound.Instance.spectateCamera;
			return ((Object)(object)spectateCamera == (Object)null) ? null : ((Component)spectateCamera).GetComponent<Light>();
		}

		private void ReadScroll(PlayerControllerB player)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || player.playerActions == null || IsMenuOpen())
			{
				lastScroll = 0f;
				return;
			}
			MovementActions movement = player.playerActions.Movement;
			float value = ((MovementActions)(ref movement)).SwitchItem.ReadValue<float>();
			int num = Sign(value);
			int num2 = Sign(lastScroll);
			lastScroll = value;
			if (num != 0 && num != num2)
			{
				if (Mode == SpectateMode.FreeCam)
				{
					FreeCamSpeed = Mathf.Clamp(FreeCamSpeed + (float)num, 1f, 40f);
				}
				else if (Mode == SpectateMode.Ghost)
				{
					GhostBody.FlySpeed = Mathf.Clamp(GhostBody.FlySpeed + (float)num, 1f, 40f);
				}
				else if (SpectatingEnemies)
				{
					ZoomLevel = Mathf.Clamp(ZoomLevel - (float)num * 0.1f, 1f, 10f);
				}
			}
		}

		private static int Sign(float value)
		{
			if (value > 0.3f)
			{
				return 1;
			}
			return (value < -0.3f) ? (-1) : 0;
		}

		internal static void SaveConfig()
		{
			if (Plugin.Configuration != null)
			{
				Plugin.Configuration.Save();
			}
		}

		private Vector3 Viewpoint()
		{
			//IL_004d: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController);
			if (Mode == SpectateMode.Ghost && (Object)(object)val != (Object)null && (Object)(object)val.gameplayCamera != (Object)null)
			{
				return ((Component)val.gameplayCamera).transform.position;
			}
			Camera val2 = (((Object)(object)StartOfRound.Instance == (Object)null) ? null : StartOfRound.Instance.spectateCamera);
			if ((Object)(object)val2 != (Object)null)
			{
				return ((Component)val2).transform.position;
			}
			return ((Object)(object)val == (Object)null) ? Vector3.zero : ((Component)val).transform.position;
		}

		internal void SetFreeCamPosition(Vector3 point)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			camPosition = point;
		}

		private void ReadHotkeys()
		{
			if (IsMenuOpen())
			{
				return;
			}
			Keyboard current = Keyboard.current;
			if (current != null)
			{
				if (((ButtonControl)current.fKey).wasPressedThisFrame)
				{
					ToggleLight();
				}
				if (Mode == SpectateMode.Ghost && ((ButtonControl)current.nKey).wasPressedThisFrame)
				{
					GhostBody.SetNoClip(!GhostBody.NoClip);
					Dock.Toast(GhostBody.NoClip ? "No clip on" : "No clip off");
				}
			}
		}

		private void LateUpdate()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			if (CanControlCamera())
			{
				ReadScroll(GameNetworkManager.Instance.localPlayerController);
				ReadHotkeys();
				RenderView.Tick(Viewpoint());
			}
			else
			{
				RenderView.Restore();
				Doorways.Forget();
			}
			if (Mode == SpectateMode.Ghost)
			{
				if (!StillDead())
				{
					SetMode(SpectateMode.Spectate);
					return;
				}
				GhostBody.LateTick();
				Doorways.Tick();
				return;
			}
			if (Mode == SpectateMode.FreeCam)
			{
				UpdateFreeCam();
				if (Mode == SpectateMode.FreeCam)
				{
					Doorways.Tick();
				}
				return;
			}
			Doorways.Forget();
			if (!SpectatingEnemies)
			{
				return;
			}
			if (anchorName.Length > 0)
			{
				if ((Object)(object)anchor == (Object)null)
				{
					ClearAnchor();
					SpectatingEnemies = false;
					Plugin.displaySpectatorTip.Invoke(HUDManager.Instance, new object[1] { "That body is gone" });
				}
				else
				{
					ParkCamera(anchor.position, anchorName);
				}
				return;
			}
			if (SpectatorList == null || SpectatorList.Length == 0)
			{
				SpectatingEnemies = false;
				return;
			}
			Spectatable obj = SpectatorList.ElementAtOrDefault(SpectatedEnemyIndex);
			if ((Object)(object)obj == (Object)null || (Object)(object)obj.enemyInstance == (Object)null || obj.enemyInstance.isEnemyDead)
			{
				GetNextValidSpectatable();
				return;
			}
			Vector3? spectatePosition = GetSpectatePosition(obj);
			if (!spectatePosition.HasValue)
			{
				GetNextValidSpectatable();
				return;
			}
			if (obj.enemyName == "Enemy")
			{
				TryFixName(ref obj);
			}
			string label;
			if (obj.type == SpectatableType.Masked && obj.maskedName != string.Empty)
			{
				label = obj.maskedName;
			}
			else if (obj.type == SpectatableType.GhostGirl)
			{
				DressGirlAI component = ((Component)obj).gameObject.GetComponent<DressGirlAI>();
				((EnemyAI)component).EnableEnemyMesh(true, true, true);
				PlayerControllerB targetPlayer = ((EnemyAI)component).targetPlayer;
				label = (((Object)(object)targetPlayer != (Object)null) ? (obj.maskedName + "\n(Targeting: " + targetPlayer.playerUsername + ")") : (obj.maskedName + "\n(No Target)"));
			}
			else
			{
				label = obj.enemyName;
			}
			ParkCamera(spectatePosition.Value, label);
		}

		private static bool StillDead()
		{
			PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController);
			return (Object)(object)val != (Object)null && (Object)(object)StartOfRound.Instance != (Object)null && val.isPlayerDead && !StartOfRound.Instance.shipIsLeaving;
		}

		private void ParkCamera(Vector3 point, string label)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if (!((Object)(object)localPlayerController == (Object)null) && !((Object)(object)localPlayerController.spectateCameraPivot == (Object)null))
			{
				localPlayerController.spectateCameraPivot.position = point;
				if ((Object)(object)HUDManager.Instance != (Object)null)
				{
					((TMP_Text)HUDManager.Instance.spectatingPlayerText).text = $"(Spectating: {label}) [{ZoomLevel:F1}x]";
				}
				Plugin.raycastSpectate.Invoke(localPlayerController, Array.Empty<object>());
				((Component)((Component)localPlayerController.spectateCameraPivot).GetComponentInChildren<Camera>()).transform.localPosition = Vector3.back * (ZoomLevel + 0.5f);
			}
		}

		private Vector3? GetSpectatePosition(Spectatable obj)
		{
			//IL_004d: 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)
			EnemyAI val = (((Object)(object)obj == (Object)null) ? null : obj.enemyInstance);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			return ((Object)(object)val.eye == (Object)null) ? ((Component)val).transform.position : val.eye.position;
		}

		private void TryFixName(ref Spectatable obj)
		{
			MaskedPlayerEnemy val = default(MaskedPlayerEnemy);
			EnemyAI val2 = default(EnemyAI);
			if (((Component)obj).gameObject.TryGetComponent<MaskedPlayerEnemy>(ref val))
			{
				obj.enemyName = (((Object)(object)val.mimickingPlayer != (Object)null) ? val.mimickingPlayer.playerUsername : ((EnemyAI)val).enemyType.enemyName);
			}
			else if (((Component)obj).gameObject.TryGetComponent<EnemyAI>(ref val2))
			{
				obj.enemyName = val2.enemyType.enemyName;
			}
		}

		internal bool SpectateTarget(Spectatable target)
		{
			if ((Object)(object)target == (Object)null || (Object)(object)GameNetworkManager.Instance == (Object)null)
			{
				return false;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null)
			{
				return false;
			}
			RebuildSpectatorList();
			int num = Array.IndexOf(SpectatorList, target);
			if (num < 0)
			{
				return false;
			}
			LeaveDrivenModes();
			ClearAnchor();
			SpectatedEnemyIndex = num;
			SpectatingEnemies = true;
			localPlayerController.spectatedPlayerScript = null;
			return true;
		}

		internal bool AnchorOn(Transform body, string label)
		{
			if ((Object)(object)body == (Object)null || (Object)(object)GameNetworkManager.Instance == (Object)null)
			{
				return false;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null)
			{
				return false;
			}
			LeaveDrivenModes();
			anchor = body;
			anchorName = label;
			SpectatedEnemyIndex = -1;
			SpectatingEnemies = true;
			localPlayerController.spectatedPlayerScript = null;
			return true;
		}

		private void ClearAnchor()
		{
			anchor = null;
			anchorName = string.Empty;
		}

		private void LeaveDrivenModes()
		{
			if (Mode == SpectateMode.Ghost)
			{
				GhostBody.Exit();
			}
			Mode = SpectateMode.Spectate;
		}

		internal bool SetMode(SpectateMode mode)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			if (Mode == mode || (Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
			{
				return false;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null)
			{
				return false;
			}
			SpectateMode mode2 = Mode;
			if (mode2 == SpectateMode.Ghost)
			{
				GhostBody.Exit();
			}
			Mode = mode;
			ClearAnchor();
			SpectatingEnemies = false;
			if (mode == SpectateMode.Spectate)
			{
				PlayerControllerB val = NearestLivingPlayer(camPosition);
				if ((Object)(object)val != (Object)null)
				{
					SpectatePlayer(val);
				}
				else
				{
					localPlayerController.spectatedPlayerScript = null;
				}
				return true;
			}
			Camera spectateCamera = StartOfRound.Instance.spectateCamera;
			if (mode2 == SpectateMode.Spectate && (Object)(object)spectateCamera != (Object)null)
			{
				camPosition = ((Component)spectateCamera).transform.position;
				Vector3 eulerAngles = ((Component)spectateCamera).transform.eulerAngles;
				camYaw = eulerAngles.y;
				camPitch = ((eulerAngles.x > 180f) ? (eulerAngles.x - 360f) : eulerAngles.x);
			}
			localPlayerController.spectatedPlayerScript = null;
			if (mode == SpectateMode.Ghost && !GhostBody.Enter(camPosition))
			{
				Mode = mode2;
				return false;
			}
			return true;
		}

		internal bool WarpCamera(Vector3 point)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (Mode == SpectateMode.Ghost)
			{
				return GhostBody.Warp(point);
			}
			if (Mode != SpectateMode.FreeCam)
			{
				return false;
			}
			Quaternion val = Quaternion.Euler(camPitch, camYaw, 0f);
			camPosition = point - val * Vector3.forward * 4f;
			return true;
		}

		internal Vector3? PositionOf(Spectatable target)
		{
			return ((Object)(object)target == (Object)null) ? ((Vector3?)null) : GetSpectatePosition(target);
		}

		private static PlayerControllerB NearestLivingPlayer(Vector3 from)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null)
			{
				return null;
			}
			PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController);
			PlayerControllerB result = null;
			float num = float.MaxValue;
			PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts;
			foreach (PlayerControllerB val2 in allPlayerScripts)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val) && !val2.isPlayerDead && val2.isPlayerControlled)
				{
					Vector3 val3 = ((Component)val2).transform.position - from;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = val2;
					}
				}
			}
			return result;
		}

		private void UpdateFreeCam()
		{
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00b4: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: 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_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: 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_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			if (!StillDead())
			{
				Mode = SpectateMode.Spectate;
				return;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			Camera spectateCamera = StartOfRound.Instance.spectateCamera;
			if ((Object)(object)spectateCamera == (Object)null)
			{
				return;
			}
			if (!IsMenuOpen() && localPlayerController.playerActions != null)
			{
				MovementActions movement = localPlayerController.playerActions.Movement;
				Vector2 val = ((MovementActions)(ref movement)).Look.ReadValue<Vector2>() * 0.008f * (float)IngamePlayerSettings.Instance.settings.lookSensitivity;
				camYaw += val.x;
				camPitch = Mathf.Clamp(camPitch - val.y, -89f, 89f);
				Quaternion val2 = Quaternion.Euler(camPitch, camYaw, 0f);
				movement = localPlayerController.playerActions.Movement;
				Vector2 val3 = ((MovementActions)(ref movement)).Move.ReadValue<Vector2>();
				float freeCamSpeed = FreeCamSpeed;
				movement = localPlayerController.playerActions.Movement;
				float num = freeCamSpeed * (((MovementActions)(ref movement)).Sprint.IsPressed() ? 3f : 1f) * Time.deltaTime;
				camPosition += val2 * new Vector3(val3.x, 0f, val3.y) * num;
				movement = localPlayerController.playerActions.Movement;
				if (((MovementActions)(ref movement)).Jump.IsPressed())
				{
					camPosition += Vector3.up * num;
				}
				movement = localPlayerController.playerActions.Movement;
				if (((MovementActions)(ref movement)).Crouch.IsPressed())
				{
					camPosition -= Vector3.up * num;
				}
			}
			((Component)spectateCamera).transform.SetPositionAndRotation(camPosition, Quaternion.Euler(camPitch, camYaw, 0f));
			if ((Object)(object)localPlayerController.spectateCameraPivot != (Object)null)
			{
				localPlayerController.spectateCameraPivot.position = camPosition;
			}
		}

		internal bool SpectatePlayer(PlayerControllerB target)
		{
			if ((Object)(object)target == (Object)null || (Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
			{
				return false;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null || (Object)(object)target == (Object)(object)localPlayerController)
			{
				return false;
			}
			LeaveDrivenModes();
			ClearAnchor();
			SpectatingEnemies = false;
			localPlayerController.spectatedPlayerScript = target;
			StartOfRound.Instance.SetPlayerSafeInShip();
			localPlayerController.SetSpectatedPlayerEffects(false);
			if ((Object)(object)HUDManager.Instance != (Object)null)
			{
				((TMP_Text)HUDManager.Instance.spectatingPlayerText).text = "(Spectating: " + target.playerUsername + ")";
			}
			return true;
		}

		internal void ResetState()
		{
			GhostBody.Exit();
			RenderView.Restore();
			Doorways.Forget();
			SpectatedEnemyIndex = -1;
			SpectatingEnemies = false;
			Mode = SpectateMode.Spectate;
			ClearAnchor();
			Hide();
		}

		private void RebuildSpectatorList()
		{
			SpectatorList = (from x in Object.FindObjectsByType<Spectatable>((FindObjectsSortMode)0)
				where (Object)(object)x != (Object)null && (Object)(object)x.enemyInstance != (Object)null && !x.enemyInstance.isEnemyDead
				select x).ToArray();
		}

		private void GetNextValidSpectatable()
		{
			RebuildSpectatorList();
			if (SpectatorList.Length == 0)
			{
				SpectatingEnemies = false;
				SpectatedEnemyIndex = -1;
				Plugin.displaySpectatorTip.Invoke(HUDManager.Instance, new object[1] { "No enemies to spectate" });
				return;
			}
			int num = SpectatedEnemyIndex + 1;
			if (num < 0 || num >= SpectatorList.Length)
			{
				num = 0;
			}
			SpectatedEnemyIndex = num;
		}

		public void Toggle()
		{
			if (SpectateMenu.Instance != null)
			{
				SpectateMenu.Instance.Toggle();
			}
		}

		public void Hide()
		{
			if (SpectateMenu.Instance != null)
			{
				SpectateMenu.Instance.Hide();
			}
		}

		public bool IsMenuOpen()
		{
			return SpectateMenu.Instance != null && SpectateMenu.Instance.IsOpen;
		}

		private void OnGUI()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0078: 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_007e: 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_00d8: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			if (HideControls == null || !CanControlCamera() || IsMenuOpen())
			{
				return;
			}
			OverlayStyles.EnsureBuilt();
			Doorways.DrawMarkers();
			DrawDoorPrompt();
			if (!HideControls.Value)
			{
				string text = Hint();
				if (text.Length != 0)
				{
					GUIContent val = new GUIContent(text);
					Vector2 val2 = OverlayStyles.Label.CalcSize(val);
					float num = Mathf.Max(val2.x, 150f) + 20f;
					float num2 = OverlayStyles.Label.CalcHeight(val, num - 20f) + 16f;
					Rect val3 = default(Rect);
					((Rect)(ref val3))..ctor((float)Screen.width - num - 24f, ((float)Screen.height - num2) / 2f, num, num2);
					OverlayStyles.DrawBox(val3, OverlayStyles.Background, OverlayStyles.Border);
					OverlayStyles.Fill(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y, 2f, ((Rect)(ref val3)).height), OverlayStyles.Primary);
					GUI.Label(new Rect(((Rect)(ref val3)).x + 12f, ((Rect)(ref val3)).y + 8f, ((Rect)(ref val3)).width - 20f, ((Rect)(ref val3)).height - 16f), val, OverlayStyles.Label);
				}
			}
		}

		private void DrawDoorPrompt()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			EntranceTeleport aimed = Doorways.Aimed;
			if (!((Object)(object)aimed == (Object)null))
			{
				string text = "Press [" + InteractKeyName() + "] to " + (aimed.isEntranceToBuilding ? "enter" : "leave");
				GUIContent val = new GUIContent(text);
				Vector2 val2 = OverlayStyles.Label.CalcSize(val);
				Rect val3 = default(Rect);
				((Rect)(ref val3))..ctor(((float)Screen.width - val2.x - 24f) / 2f, (float)Screen.height / 2f + 48f, val2.x + 24f, val2.y + 12f);
				OverlayStyles.DrawBox(val3, OverlayStyles.Background, OverlayStyles.Border);
				GUI.Label(new Rect(((Rect)(ref val3)).x + 12f, ((Rect)(ref val3)).y + 6f, val2.x, val2.y), val, OverlayStyles.Label);
			}
		}

		private static string InteractKeyName()
		{
			//IL_0033: 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)
			//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_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_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)
			PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController);
			if (!((Object)(object)val == (Object)null) && val.playerActions != null)
			{
				MovementActions movement = val.playerActions.Movement;
				if (((MovementActions)(ref movement)).Interact.bindings.Count != 0)
				{
					movement = val.playerActions.Movement;
					InputBinding val2 = ((MovementActions)(ref movement)).Interact.bindings[0];
					return InputControlPath.ToHumanReadableString(((InputBinding)(ref val2)).effectivePath, (HumanReadableStringOptions)2, (InputControl)null);
				}
			}
			return "E";
		}

		private string Hint()
		{
			string text = Dock.ToggleKeyName();
			return Mode switch
			{
				SpectateMode.FreeCam => "FREE CAM\n\nMenu : [" + text + "]\nFly : [Move keys]\nUp / Down : [Jump / Crouch]\nFaster : [Sprint]\nSpeed : [Scroll]\nFlashlight : [F]\nDoorways : [" + InteractKeyName() + "] at one", 
				SpectateMode.Ghost => "GHOST\n\nMenu : [" + text + "]\nFly / Land : [Double jump]\nUp / Down : [Jump / Crouch]\nFaster : [Sprint]\nSpeed : [Scroll]\nFlashlight : [F]\nNo clip : [N] (" + (GhostBody.NoClip ? "on" : "off") + ")\nDoorways : [" + InteractKeyName() + "] at one", 
				_ => SpectatingEnemies ? ("SPECTATE\n\nMenu : [" + text + "]\nZoom : [Scroll]") : ("SPECTATE\n\nMenu : [" + text + "]"), 
			};
		}
	}
	public class SpectateEnemiesAPI
	{
		public static bool IsLoaded => (Object)(object)SpectateEnemies.Instance != (Object)null;

		public static bool IsSpectatingEnemies => SpectateEnemies.Instance.SpectatingEnemies;

		public static GameObject CurrentEnemySpectating()
		{
			if (IsSpectatingEnemies && SpectateEnemies.Instance.SpectatedEnemyIndex > -1)
			{
				return ((Component)SpectateEnemies.Instance.SpectatorList[SpectateEnemies.Instance.SpectatedEnemyIndex]).gameObject;
			}
			return null;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "SpectateEnemy";

		public const string PLUGIN_NAME = "SpectateEnemy";

		public const string PLUGIN_VERSION = "2.8.0";
	}
}
namespace SpectateEnemy.UI
{
	internal sealed class SpectateMenu
	{
		private struct TargetRow
		{
			public string Name;

			public string Kind;

			public string Detail;

			public string Where;

			public float Distance;

			public bool Dead;

			public PlayerControllerB Player;

			public Spectatable Target;

			public Transform Body;

			public Vector3 Point;
		}

		private OverlayPanel _panel;

		private OverlayWindow _mode;

		private OverlayWindow _render;

		private OverlayWindow _players;

		private OverlayWindow _enemies;

		private bool _savePending;

		private readonly List<TargetRow> _rows = new List<TargetRow>();

		private readonly OverlayColumns _playerColumns = new OverlayColumns(new string[4] { "PLAYER", "HEALTH", "WHERE", "DIST" });

		private readonly OverlayColumns _enemyColumns = new OverlayColumns(new string[4] { "ENEMY", "TYPE", "WHERE", "DIST" });

		private float _nextRefresh;

		private string _playerSearch = string.Empty;

		private string _enemySearch = string.Empty;

		private TargetRow _picked;

		private bool _hasPick;

		private static float RowHeight => OverlayStyles.RowHeight;

		private static float ModeRowHeight => OverlayStyles.RowHeight + 8f;

		internal static SpectateMenu Instance { get; private set; }

		internal bool IsOpen => Dock.IsOpen;

		private bool IsFronted => Dock.IsOpen && Dock.ActivePanel == _panel;

		private static float ToggleWidth(string on, string off)
		{
			return Mathf.Max(62f, Mathf.Max(OverlayStyles.ButtonWidth(on, (GUIStyle)null), OverlayStyles.ButtonWidth(off, (GUIStyle)null)));
		}

		internal static void Register()
		{
			if (Instance == null)
			{
				Instance = new SpectateMenu();
				Instance.Build();
			}
		}

		private void Build()
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			_panel = Dock.Register("SPECTATE");
			_panel.Order = 20;
			_panel.Unavailable = () => CanSpectate() ? null : "Only available once dead";
			_mode = _panel.AddWindow("MODE", (Action<Rect>)DrawModeWindow, "mode", new Rect(60f, 90f, 540f, 250f));
			_mode.Open = true;
			_mode.Subtitle = () => ModeName(SpectateEnemies.Instance.Mode).ToLowerInvariant();
			_render = _panel.AddWindow("RENDER", (Action<Rect>)DrawRenderWindow, "eye", new Rect(620f, 450f, 460f, 200f));
			_render.Subtitle = RenderView.Summary;
			_players = _panel.AddWindow("PLAYERS", (Action<Rect>)DrawPlayersWindow, "players", new Rect(60f, 296f, 540f, 300f));
			_players.Open = true;
			_players.Subtitle = () => $"{Count(players: true)} on the crew";
			_enemies = _panel.AddWindow("ENEMIES", (Action<Rect>)DrawEnemiesWindow, "enemies", new Rect(620f, 90f, 540f, 340f));
			_enemies.Subtitle = () => $"{Count(players: false)} out there";
			Debug.Log((object)("[SpectateEnemies]: Registered the spectate panel with Overlay (open it with " + Dock.ToggleKeyName() + ")."));
		}

		private static string ModeName(SpectateMode mode)
		{
			return mode switch
			{
				SpectateMode.FreeCam => "FREE CAM", 
				SpectateMode.Ghost => "GHOST", 
				_ => "SPECTATE", 
			};
		}

		internal void Show()
		{
			if (Dock.Show(_panel))
			{
				_nextRefresh = 0f;
			}
		}

		internal void Hide()
		{
			Dock.Close();
		}

		internal void Toggle()
		{
			if (IsFronted)
			{
				Hide();
			}
			else
			{
				Show();
			}
		}

		private static bool CanSpectate()
		{
			if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null)
			{
				return false;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			return (Object)(object)localPlayerController != (Object)null && ((NetworkBehaviour)localPlayerController).IsOwner && localPlayerController.isPlayerDead && !StartOfRound.Instance.shipIsLeaving && (!((NetworkBehaviour)localPlayerController).IsServer || localPlayerController.isHostPlayerObject);
		}

		private static void Toast(string message)
		{
			Dock.Toast(message);
		}

		private void RefreshIfDue()
		{
			if (!(Time.unscaledTime < _nextRefresh))
			{
				_nextRefresh = Time.unscaledTime + 0.5f;
				RefreshTargets();
			}
		}

		private void RefreshTargets()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: 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_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_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			_rows.Clear();
			_playerColumns.Reset();
			_enemyColumns.Reset();
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController);
			Vector3 val2 = From(val);
			if (instance.allPlayerScripts != null)
			{
				PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts;
				foreach (PlayerControllerB val3 in allPlayerScripts)
				{
					if (!((Object)(object)val3 == (Object)null) && (val3.isPlayerControlled || val3.isPlayerDead))
					{
						bool isPlayerDead = val3.isPlayerDead;
						Transform val4 = BodyOf(val3);
						string name = (((Object)(object)val3 == (Object)(object)val) ? (val3.playerUsername + " (you)") : val3.playerUsername);
						Vector3 val5 = ((isPlayerDead && (Object)(object)val4 != (Object)null) ? val4.position : (((Object)(object)val3.lowerSpine != (Object)null) ? (val3.lowerSpine.position + Vector3.up * 0.7f) : (((Component)val3).transform.position + Vector3.up * 1.5f)));
						_rows.Add(new TargetRow
						{
							Name = name,
							Kind = (isPlayerDead ? "BODY" : "PLAYER"),
							Detail = ((!isPlayerDead) ? $"{Mathf.Max(0, val3.health)} HP" : (((Object)(object)val4 == (Object)null) ? "NO BODY" : "DEAD")),
							Where = (val3.isInsideFactory ? "INSIDE" : "OUTSIDE"),
							Distance = Vector3.Distance(val2, val5),
							Dead = isPlayerDead,
							Player = val3,
							Body = val4,
							Point = val5
						});
					}
				}
			}
			Spectatable[] array = Object.FindObjectsByType<Spectatable>((FindObjectsSortMode)0);
			foreach (Spectatable spectatable in array)
			{
				if (!((Object)(object)spectatable == (Object)null) && !((Object)(object)spectatable.enemyInstance == (Object)null))
				{
					EnemyAI enemyInstance = spectatable.enemyInstance;
					bool isEnemyDead = enemyInstance.isEnemyDead;
					Vector3 val6 = (Vector3)(isEnemyDead ? ((Component)enemyInstance).transform.position : (((??)SpectateEnemies.Instance.PositionOf(spectatable)) ?? ((Component)enemyInstance).transform.position));
					_rows.Add(new TargetRow
					{
						Name = DisplayName(spectatable),
						Kind = (isEnemyDead ? "CORPSE" : KindOf(spectatable.type)),
						Detail = (isEnemyDead ? "DEAD" : KindOf(spectatable.type)),
						Where = (enemyInstance.isOutside ? "OUTSIDE" : "INSIDE"),
						Distance = Vector3.Distance(val2, val6),
						Dead = isEnemyDead,
						Target = spectatable,
						Body = (isEnemyDead ? ((Component)enemyInstance).transform : null),
						Point = val6
					});
				}
			}
			_rows.Sort((TargetRow a, TargetRow b) => (a.Dead != b.Dead) ? (a.Dead ? 1 : (-1)) : a.Distance.CompareTo(b.Distance));
		}

		private static Vector3 From(PlayerControllerB local)
		{
			//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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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)
			if ((Object)(object)local == (Object)null)
			{
				return Vector3.zero;
			}
			if (GhostBody.Active)
			{
				return ((Component)local).transform.position;
			}
			return ((Object)(object)local.spectateCameraPivot != (Object)null) ? local.spectateCameraPivot.position : ((Component)local).transform.position;
		}

		private static Transform BodyOf(PlayerControllerB player)
		{
			if (!player.isPlayerDead || (Object)(object)player.deadBody == (Object)null || !((Component)player.deadBody).gameObject.activeSelf)
			{
				return null;
			}
			return (player.deadBody.bodyParts != null && player.deadBody.bodyParts.Length != 0 && (Object)(object)player.deadBody.bodyParts[0] != (Object)null) ? ((Component)player.deadBody.bodyParts[0]).transform : ((Component)player.deadBody).transform;
		}

		private static string KindOf(SpectatableType type)
		{
			return type switch
			{
				SpectatableType.Masked => "MASKED", 
				SpectatableType.GhostGirl => "GHOST", 
				_ => "ENEMY", 
			};
		}

		private static string DisplayName(Spectatable target)
		{
			if (target.type == SpectatableType.Masked && !string.IsNullOrEmpty(target.maskedName))
			{
				return target.maskedName;
			}
			if (!string.IsNullOrEmpty(target.enemyName) && target.enemyName != "Enemy")
			{
				return target.enemyName;
			}
			return ((Object)(object)target.enemyInstance != (Object)null && (Object)(object)target.enemyInstance.enemyType != (Object)null) ? target.enemyInstance.enemyType.enemyName : "Enemy";
		}

		private void Select(TargetRow row)
		{
			//IL_009a: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			SpectateEnemies instance = SpectateEnemies.Instance;
			if ((Object)(object)row.Player == (Object)null && (Object)(object)row.Target == (Object)null)
			{
				Toast("That target is gone");
				RefreshTargets();
				return;
			}
			if (row.Dead && (Object)(object)row.Body == (Object)null)
			{
				Toast("There is no body left of " + row.Name);
				RefreshTargets();
				return;
			}
			Vector3 point = (((Object)(object)row.Body != (Object)null) ? row.Body.position : row.Point);
			if (instance.Mode != SpectateMode.Spectate)
			{
				if (instance.WarpCamera(point))
				{
					Toast(((instance.Mode == SpectateMode.Ghost) ? "Walked to " : "Flew to ") + row.Name);
					Hide();
				}
				else
				{
					Toast("Could not move to " + row.Name);
					RefreshTargets();
				}
				return;
			}
			if (row.Dead)
			{
				if (instance.AnchorOn(row.Body, row.Name))
				{
					Toast("Watching the body of " + row.Name);
					Hide();
					return;
				}
			}
			else if ((Object)(object)row.Player != (Object)null)
			{
				if (instance.SpectatePlayer(row.Player))
				{
					Toast("Spectating " + row.Name);
					Hide();
					return;
				}
			}
			else if (instance.SpectateTarget(row.Target))
			{
				Toast("Spectating " + row.Name);
				Hide();
				return;
			}
			Toast("Could not spectate " + row.Name);
			RefreshTargets();
		}

		private void DrawModeWindow(Rect content)
		{
			//IL_0010: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_013e: 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_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			SpectateEnemies instance = SpectateEnemies.Instance;
			float y = ((Rect)(ref content)).y;
			y = DrawModeRow(content, y, SpectateMode.Spectate, "Watch a player, an enemy or a body. Picking a live target locks onto it.");
			y = DrawModeRow(content, y, SpectateMode.FreeCam, $"Fly through everything, {instance.FreeCamSpeed:F0} m/s. Picking a target flies you to it.");
			y = DrawModeRow(content, y, SpectateMode.Ghost, GhostBody.Flying ? "Flying. Jump and crouch for up and down, double jump to land." : "Walk about as if alive: your body, scan, no stamina. Double jump to fly.");
			y += 6f;
			OverlayStyles.Fill(new Rect(((Rect)(ref content)).x, y, ((Rect)(ref content)).width, 1f), new Color(1f, 1f, 1f, 0.12f));
			y += 7f;
			float num = ToggleWidth("ON", "OFF");
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref content)).x, y, ((Rect)(ref content)).width, RowHeight);
			GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, Mathf.Max(0f, ((Rect)(ref val)).width - num - 8f), ((Rect)(ref val)).height), (instance.Mode == SpectateMode.Ghost) ? "Helmet light" : "Spectator flashlight", OverlayStyles.Label);
			bool lightOn = instance.LightOn;
			if (OverlayStyles.Press(new Rect(((Rect)(ref val)).xMax - num, ((Rect)(ref val)).y, num, RowHeight), lightOn ? "ON" : "OFF", lightOn ? OverlayStyles.ButtonActive : OverlayStyles.Button))
			{
				instance.ToggleLight();
			}
			y += RowHeight + 2f;
			if (instance.Mode == SpectateMode.Ghost)
			{
				float num2 = ToggleWidth("ON", "OFF");
				Rect val2 = default(Rect);
				((Rect)(ref val2))..ctor(((Rect)(ref content)).x, y, ((Rect)(ref content)).width, RowHeight);
				GUI.Label(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y, Mathf.Max(0f, ((Rect)(ref val2)).width - num2 - 8f), ((Rect)(ref val2)).height), "Walk through walls  [N]", OverlayStyles.Label);
				bool noClip = GhostBody.NoClip;
				if (OverlayStyles.Press(new Rect(((Rect)(ref val2)).xMax - num2, ((Rect)(ref val2)).y, num2, RowHeight), noClip ? "ON" : "OFF", noClip ? OverlayStyles.ButtonActive : OverlayStyles.Button))
				{
					GhostBody.SetNoClip(!noClip);
				}
				y += RowHeight + 2f;
			}
			y = DrawVoteRow(content, y);
			float num3 = ToggleWidth("HIDDEN", "SHOWN");
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(((Rect)(ref content)).x, y, ((Rect)(ref content)).width, RowHeight);
			GUI.Label(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y, Mathf.Max(0f, ((Rect)(ref val3)).width - num3 - 8f), ((Rect)(ref val3)).height), "Controls hint on the HUD", OverlayStyles.Label);
			bool value = instance.HideControls.Value;
			if (OverlayStyles.Press(new Rect(((Rect)(ref val3)).xMax - num3, ((Rect)(ref val3)).y, num3, RowHeight), value ? "HIDDEN" : "SHOWN", value ? OverlayStyles.ButtonActive : OverlayStyles.Button))
			{
				instance.HideControls.Value = !value;
				_savePending = true;
			}
			y += RowHeight + 4f;
			float num4 = OverlayStyles.TextHeight("Overlay's key is the only one that opens this. While dead: [F] for the light, [N] for no clip in ghost mode, and your interact key at a highlighted doorway.", ((Rect)(ref content)).width - 20f, OverlayStyles.LabelMuted);
			_mode.FitContentHeight(y - ((Rect)(ref content)).y + num4);
			OverlayStyles.Paragraph(new Rect(((Rect)(ref content)).x, Mathf.Max(y, ((Rect)(ref content)).yMax - num4), ((Rect)(ref content)).width - 20f, num4), "Overlay's key is the only one that opens this. While dead: [F] for the light, [N] for no clip in ghost mode, and your interact key at a highlighted doorway.", OverlayStyles.LabelMuted);
			SaveWhenSettled();
		}

		private static float DrawVoteRow(Rect content, float y)
		{
			//IL_00e2: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref content)).x, y, ((Rect)(ref content)).width, RowHeight);
			TimeOfDay instance = TimeOfDay.Instance;
			StartOfRound instance2 = StartOfRound.Instance;
			if (!((Object)(object)instance != (Object)null) || !((Object)(object)instance2 != (Object)null) || instance2.shipIsLeaving || !((Object)(object)instance2.currentLevel != (Object)null) || !instance2.currentLevel.planetHasTime || instance.shipLeavingAlertCalled)
			{
				GUI.Label(val, "Ship cannot be voted off this planet", OverlayStyles.LabelMuted);
				return y + RowHeight + 2f;
			}
			bool votedShipToLeaveEarlyThisRound = instance.votedShipToLeaveEarlyThisRound;
			float num = ToggleWidth("VOTED", "VOTE");
			GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, Mathf.Max(0f, ((Rect)(ref val)).width - num - 8f), ((Rect)(ref val)).height), $"Tell the autopilot to leave early  ({instance.votesForShipToLeaveEarly} voted)", votedShipToLeaveEarlyThisRound ? OverlayStyles.LabelMuted : OverlayStyles.Label);
			if (OverlayStyles.Press(new Rect(((Rect)(ref val)).xMax - num, ((Rect)(ref val)).y, num, RowHeight), votedShipToLeaveEarlyThisRound ? "VOTED" : "VOTE", votedShipToLeaveEarlyThisRound ? OverlayStyles.ButtonActive : OverlayStyles.Button) && !votedShipToLeaveEarlyThisRound)
			{
				instance.VoteShipToLeaveEarly();
				Toast("Voted for the ship to leave early");
			}
			return y + RowHeight + 2f;
		}

		private float DrawModeRow(Rect content, float y, SpectateMode mode, string description)
		{
			//IL_0075: 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_0161: Unknown result type (might be due to invalid IL or missing references)
			SpectateEnemies instance = SpectateEnemies.Instance;
			bool flag = instance.Mode == mode;
			float num = Mathf.Max(96f, OverlayStyles.ButtonWidth(ModeName(mode), (GUIStyle)null));
			float num2 = Mathf.Max(ModeRowHeight, OverlayStyles.TextHeight(description, Mathf.Max(40f, ((Rect)(ref content)).width - num - 13f), OverlayStyles.Label) + 6f);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref content)).x, y, ((Rect)(ref content)).width, num2);
			GUI.Label(val, GUIContent.none, flag ? OverlayStyles.RowHover : OverlayStyles.Row);
			if (OverlayStyles.Press(new Rect(((Rect)(ref val)).x + 3f, ((Rect)(ref val)).y + 3f, num, ModeRowHeight - 6f), ModeName(mode), flag ? OverlayStyles.ButtonActive : OverlayStyles.Button))
			{
				if (instance.SetMode(mode))
				{
					Toast(ModeName(mode) + " mode");
				}
				else if (!flag)
				{
					Toast("Could not switch to " + ModeName(mode));
				}
			}
			OverlayStyles.Paragraph(new Rect(((Rect)(ref val)).x + num + 9f, ((Rect)(ref val)).y + 3f, Mathf.Max(40f, ((Rect)(ref val)).width - num - 13f), 0f), description, flag ? OverlayStyles.Label : OverlayStyles.LabelMuted);
			return y + ((Rect)(ref val)).height + 2f;
		}

		private void DrawRenderWindow(Rect content)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			OverlayLayout val = _render.Begin(content);
			((OverlayNode)val).Paragraph("What you see while you are dead. Kept between deaths.", OverlayStyles.LabelMuted);
			((OverlayNode)val).Rule();
			bool flag = RenderView.Brightness.Value > 0.01f;
			float num = ((OverlayBox)val).Slider("Brightness", "spectate.brightness", RenderView.Brightness.Value, 0f, 5f, "0.##", flag ? OverlayStyles.LabelStrong : OverlayStyles.Label);
			if (!Mathf.Approximately(num, RenderView.Brightness.Value))
			{
				RenderView.Brightness.Value = num;
				_savePending = true;
			}
			bool flag2 = !RenderView.FogOff.Value;
			if (((OverlayBox)val).Toggle("Volumetric fog", flag2, "SHOWN", "HIDDEN", flag2 ? OverlayStyles.Label : OverlayStyles.LabelStrong))
			{
				RenderView.FogOff.Value = flag2;
				_savePending = true;
			}
			((OverlayNode)val).Rule();
			((OverlayNode)val).Paragraph("0 brightness is the game's own lighting; 1 is about what the night vision gives you inside. The light follows whatever you are looking out of, so it works outside as well.", OverlayStyles.LabelMuted);
			SaveWhenSettled();
		}

		private void SaveWhenSettled()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			if (_savePending && (int)Event.current.type == 7)
			{
				Mouse current = Mouse.current;
				if (current == null || !current.leftButton.isPressed)
				{
					_savePending = false;
					SpectateEnemies.SaveConfig();
				}
			}
		}

		private void DrawPlayersWindow(Rect content)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			DrawList(content, _players, players: true, ref _playerSearch);
		}

		private void DrawEnemiesWindow(Rect content)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			DrawList(content, _enemies, players: false, ref _enemySearch);
		}

		private void DrawList(Rect content, OverlayWindow window, bool players, ref string search)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: 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_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0531: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: 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_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			RefreshIfDue();
			float num = OverlayStyles.ButtonWidth("CLEAR", (GUIStyle)null);
			float num2 = OverlayStyles.ButtonWidth("REFRESH", (GUIStyle)null);
			window.FitContentWidth(120f + num + num2 + 12f);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref content)).x, ((Rect)(ref content)).y, ((Rect)(ref content)).width, RowHeight);
			search = GUI.TextField(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, Mathf.Max(40f, ((Rect)(ref val)).width - num - num2 - 12f), RowHeight), search ?? string.Empty, OverlayStyles.Field);
			if (OverlayStyles.Press(new Rect(((Rect)(ref val)).xMax - num - num2 - 6f, ((Rect)(ref val)).y, num, RowHeight), "CLEAR", OverlayStyles.Button))
			{
				search = string.Empty;
				GUIUtility.keyboardControl = 0;
			}
			if (OverlayStyles.Press(new Rect(((Rect)(ref val)).xMax - num2, ((Rect)(ref val)).y, num2, RowHeight), "REFRESH", OverlayStyles.Button))
			{
				RefreshTargets();
			}
			OverlayColumns val2 = (players ? _playerColumns : _enemyColumns);
			val2.Fit(window, 14f);
			float num3 = RowHeight + 6f;
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(((Rect)(ref content)).x, ((Rect)(ref content)).y + num3, ((Rect)(ref content)).width, RowHeight);
			val2.DrawHeaders(val3);
			OverlayStyles.Fill(new Rect(((Rect)(ref content)).x, ((Rect)(ref content)).y + num3 + RowHeight, ((Rect)(ref content)).width, 1f), new Color(1f, 1f, 1f, 0.12f));
			List<TargetRow> list = Filtered(players, search);
			string text = Footer(players);
			float num4 = OverlayStyles.TextHeight(text, ((Rect)(ref content)).width - 20f, OverlayStyles.LabelMuted);
			Rect val4 = default(Rect);
			((Rect)(ref val4))..ctor(((Rect)(ref content)).x, ((Rect)(ref content)).y + num3 + RowHeight + 5f, ((Rect)(ref content)).width, Mathf.Max(RowHeight, ((Rect)(ref content)).height - num3 - RowHeight - 5f - num4));
			Rect val5 = default(Rect);
			((Rect)(ref val5))..ctor(0f, 0f, ((Rect)(ref val4)).width - 14f, (float)list.Count * RowHeight);
			window.Scroll = GUI.BeginScrollView(val4, window.Scroll, val5);
			Spectatable currentTarget = SpectateEnemies.Instance.CurrentTarget;
			Transform currentAnchor = SpectateEnemies.Instance.CurrentAnchor;
			PlayerControllerB val6 = WatchedPlayer();
			Rect val7 = default(Rect);
			for (int i = 0; i < list.Count; i++)
			{
				TargetRow picked = list[i];
				((Rect)(ref val7))..ctor(0f, (float)i * RowHeight, ((Rect)(ref val5)).width, RowHeight);
				if (!(((Rect)(ref val7)).yMax < window.Scroll.y) && !(((Rect)(ref val7)).y > window.Scroll.y + ((Rect)(ref val4)).height))
				{
					bool flag = ((!picked.Dead) ? (((Object)(object)picked.Player != (Object)null) ? ((Object)(object)picked.Player == (Object)(object)val6) : ((Object)(object)picked.Target != (Object)null && (Object)(object)picked.Target == (Object)(object)currentTarget)) : ((Object)(object)currentAnchor != (Object)null && (Object)(object)picked.Body == (Object)(object)currentAnchor));
					bool flag2 = ((Rect)(ref val7)).Contains(Event.current.mousePosition);
					GUIStyle val8 = ((flag2 || flag) ? OverlayStyles.RowHover : ((i % 2 == 0) ? OverlayStyles.Row : OverlayStyles.RowAlt));
					GUI.Label(val7, GUIContent.none, val8);
					if (flag2 && (int)Event.current.type == 0 && Event.current.button == 0)
					{
						_picked = picked;
						_hasPick = true;
						Event.current.Use();
					}
					GUIStyle val9 = (flag ? OverlayStyles.LabelAlert : (picked.Dead ? OverlayStyles.LabelMuted : OverlayStyles.Label));
					val2.DrawCell(val7, 0, flag ? (picked.Name + "  <") : picked.Name, val9);
					val2.DrawCell(val7, 1, picked.Detail, OverlayStyles.LabelMuted);
					val2.DrawCell(val7, 2, picked.Where, OverlayStyles.LabelMuted);
					val2.DrawCell(val7, 3, $"{picked.Distance:F0}m", OverlayStyles.LabelMuted);
				}
			}
			GUI.EndScrollView();
			if (_hasPick)
			{
				_hasPick = false;
				Select(_picked);
			}
			if (list.Count == 0)
			{
				GUI.Label(val4, players ? "  Nobody on the crew to show." : "  Nothing out there right now.", OverlayStyles.LabelMuted);
			}
			OverlayStyles.Paragraph(new Rect(((Rect)(ref content)).x, ((Rect)(ref content)).yMax - num4, ((Rect)(ref content)).width - 20f, num4), text, OverlayStyles.LabelMuted);
		}

		private static string Footer(bool players)
		{
			return SpectateEnemies.Instance.Mode switch
			{
				SpectateMode.FreeCam => "Free cam: clicking a row flies you to it. Change that on the MODE window.", 
				SpectateMode.Ghost => "Ghost: clicking a row walks you to it. Change that on the MODE window.", 
				_ => players ? "Click somebody to watch them. Click a body to go and look at it." : "Click an enemy to watch it. Click a corpse to go and look at it.", 
			};
		}

		private int Count(bool players)
		{
			int num = 0;
			foreach (TargetRow row in _rows)
			{
				if ((Object)(object)row.Player != (Object)null == players)
				{
					num++;
				}
			}
			return num;
		}

		private List<TargetRow> Filtered(bool players, string search)
		{
			string text = (string.IsNullOrEmpty(search) ? null : search.Trim());
			List<TargetRow> list = new List<TargetRow>();
			foreach (TargetRow row in _rows)
			{
				if ((Object)(object)row.Player != (Object)null == players && (text == null || row.Name.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0 || row.Kind.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0))
				{
					list.Add(row);
				}
			}
			return list;
		}

		private static PlayerControllerB WatchedPlayer()
		{
			if (SpectateEnemies.Instance.SpectatingEnemies || SpectateEnemies.Instance.Mode != SpectateMode.Spectate)
			{
				return null;
			}
			PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController);
			return ((Object)(object)val == (Object)null) ? null : val.spectatedPlayerScript;
		}
	}
}
namespace SpectateEnemy.Patches
{
	[HarmonyPatch(typeof(DressGirlAI), "Start")]
	internal class DressGirlAI_Patches
	{
		private static void Postfix(DressGirlAI __instance)
		{
			Spectatable spectatable = ((Component)__instance).gameObject.GetComponent<Spectatable>();
			if ((Object)(object)spectatable == (Object)null)
			{
				spectatable = ((Component)__instance).gameObject.AddComponent<Spectatable>();
				spectatable.enemyName = ((EnemyAI)__instance).enemyType.enemyName;
				spectatable.enemyInstance = (EnemyAI)(object)__instance;
			}
			spectatable.type = SpectatableType.GhostGirl;
		}
	}
	[HarmonyPatch(typeof(EnemyAI), "Start")]
	internal class EnemyAI_Patches
	{
		private static void Postfix(EnemyAI __instance)
		{
			Spectatable spectatable = ((Component)__instance).gameObject.AddComponent<Spectatable>();
			spectatable.enemyName = __instance.enemyType.enemyName;
			spectatable.enemyInstance = __instance;
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "Disconnect")]
	internal class GameNetworkManager_Disconnect
	{
		private static void Postfix()
		{
			if ((Object)(object)SpectateEnemies.Instance != (Object)null)
			{
				SpectateEnemies.Instance.ResetState();
			}
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager), "OnApplicationQuit")]
	internal class GameNetworkManager_Quit
	{
		private static void Prefix()
		{
			if ((Object)(object)SpectateEnemies.Instance != (Object)null)
			{
				Plugin.Configuration.Save();
				Debug.LogWarning((object)"[SpectateEnemies]: Config saved");
			}
		}
	}
	[HarmonyPatch(typeof(RoundManager), "PlayAudibleNoise")]
	internal class RoundManager_GhostNoise
	{
		private const float SameSpot = 1.5f;

		private static bool Prefix(Vector3 noisePosition)
		{
			//IL_0033: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!GhostBody.Active || (Object)(object)GameNetworkManager.Instance == (Object)null)
			{
				return true;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			int result;
			if (!((Object)(object)localPlayerController == (Object)null))
			{
				Vector3 val = noisePosition - ((Component)localPlayerController).transform.position;
				result = ((((Vector3)(ref val)).sqrMagnitude > 2.25f) ? 1 : 0);
			}
			else
			{
				result = 1;
			}
			return (byte)result != 0;
		}
	}
	[HarmonyPatch(typeof(EnemyAICollisionDetect), "OnTriggerStay")]
	internal class EnemyAICollisionDetect_GhostPass
	{
		private static bool Prefix(Collider other)
		{
			if (!GhostBody.Active || (Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)other == (Object)null)
			{
				return true;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			return (Object)(object)localPlayerController == (Object)null || (Object)(object)((Component)other).gameObject != (Object)(object)((Component)localPlayerController).gameObject;
		}
	}
	[HarmonyPatch(typeof(NutcrackerEnemyAI), "CheckLineOfSightForLocalPlayer")]
	internal class NutcrackerEnemyAI_GhostSight
	{
		private static bool Prefix(ref bool __result)
		{
			if (!GhostBody.Active)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(HUDManager), "Update")]
	internal class HUDManager_Patches
	{
		private static readonly FieldRef<HUDManager, float> EndGameHoldTime = AccessTools.FieldRefAccess<HUDManager, float>("holdButtonToEndGameEarlyHoldTime");

		private static void Postfix(HUDManager __instance)
		{
			if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)
			{
				return;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if (!localPlayerController.isPlayerDead)
			{
				return;
			}
			if (StartOfRound.Instance.shipIsLeaving)
			{
				SpectateEnemies.Instance.Hide();
				Light component = ((Component)__instance.playersManager.spectateCamera).GetComponent<Light>();
				if ((Object)(object)component != (Object)null)
				{
					((Behaviour)component).enabled = false;
				}
				return;
			}
			SetTopLine(__instance);
			if (GhostBody.Active)
			{
				EndGameHoldTime.Invoke(__instance) = 0f;
				((Component)__instance.holdButtonToEndGameEarlyMeter).gameObject.SetActive(false);
				((TMP_Text)__instance.holdButtonToEndGameEarlyText).text = "";
			}
		}

		private static void SetTopLine(HUDManager hud)
		{
			SpectateEnemies instance = SpectateEnemies.Instance;
			string text;
			if (GhostBody.Active)
			{
				text = (GhostBody.Flying ? $"(Ghost Mode - Flying) [{GhostBody.FlySpeed:F0} m/s]" : "(Ghost Mode)");
			}
			else if (instance.Mode == SpectateMode.FreeCam)
			{
				text = $"(Free Cam) [{instance.FreeCamSpeed:F0} m/s]";
			}
			else
			{
				if (instance.SpectatingEnemies)
				{
					return;
				}
				PlayerControllerB spectatedPlayerScript = GameNetworkManager.Instance.localPlayerController.spectatedPlayerScript;
				text = (((Object)(object)spectatedPlayerScript != (Object)null) ? ("(Spectating: " + spectatedPlayerScript.playerUsername + ")") : "(Nothing to watch - pick something in the spectate menu)");
			}
			if (((TMP_Text)hud.spectatingPlayerText).text != text)
			{
				((TMP_Text)hud.spectatingPlayerText).text = text;
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager), "CanPlayerScan")]
	internal class HUDManager_CanPlayerScan
	{
		private static void Postfix(ref bool __result)
		{
			if (GhostBody.Active && !((Object)(object)GameNetworkManager.Instance == (Object)null))
			{
				PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
				__result = (Object)(object)localPlayerController != (Object)null && !localPlayerController.inSpecialInteractAnimation;
			}
		}
	}
	[HarmonyPatch(typeof(MaskedPlayerEnemy), "Start")]
	internal class MaskedPlayerEnemy_Patches
	{
		private static void Postfix(MaskedPlayerEnemy __instance)
		{
			Spectatable spectatable = ((Component)__instance).gameObject.AddComponent<Spectatable>();
			spectatable.type = SpectatableType.Masked;
			spectatable.enemyName = ((EnemyAI)__instance).enemyType.enemyName;
			if ((Object)(object)__instance.mimickingPlayer != (Object)null)
			{
				spectatable.maskedName = __instance.mimickingPlayer.playerUsername;
			}
			spectatable.enemyInstance = (EnemyAI)(object)__instance;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "ActivateItem_performed")]
	internal class PlayerControllerB_Use
	{
		private static bool Prefix(PlayerControllerB __instance)
		{
			if ((Object)(object)SpectateEnemies.Instance != (Object)null && SpectateEnemies.Instance.IsMenuOpen())
			{
				return false;
			}
			return !((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerDead || (((NetworkBehaviour)__instance).IsServer && !__instance.isHostPlayerObject);
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "SpectateNextPlayer")]
	internal class PlayerControllerB_SpectateNext
	{
		private static bool Prefix(bool getClosest)
		{
			if (!getClosest)
			{
				return false;
			}
			return !SpectateEnemies.Instance.SpectatingEnemies && SpectateEnemies.Instance.Mode == SpectateMode.Spectate;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "SetWhoToSpectate")]
	internal class PlayerControllerB_SetWhoToSpectate
	{
		private static bool Prefix()
		{
			return !SpectateEnemies.Instance.SpectatingEnemies && SpectateEnemies.Instance.Mode == SpectateMode.Spectate;
		}
	}
	[