Decompiled source of EnemySpectate v1.1.2

EnemySpectate.dll

Decompiled 3 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EnemySpectate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EnemySpectate")]
[assembly: AssemblyTitle("EnemySpectate")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 EnemySpectate
{
	public class Class1
	{
	}
	[BepInPlugin("com.enemyspectate.plugin", "EnemySpectate", "1.0.0")]
	[BepInProcess("ULTRAKILL.exe")]
	public class EnemySpectatePlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static EnemySpectatePlugin Instance;

		private ConfigEntry<float> _cfgCameraFOV;

		private ConfigEntry<float> _cfgCameraOrbitDistance;

		private ConfigEntry<float> _cfgCameraOrbitMinDistance;

		private ConfigEntry<float> _cfgCameraOrbitMaxDistance;

		private ConfigEntry<float> _cfgCameraFollowDistance;

		private ConfigEntry<float> _cfgCameraFollowMinDistance;

		private ConfigEntry<float> _cfgCameraFollowMaxDistance;

		private ConfigEntry<float> _cfgCameraFollowHeightMultiplier;

		private ConfigEntry<float> _cfgCameraOrbitSensitivity;

		private ConfigEntry<float> _cfgCameraZoomSensitivity;

		private ConfigEntry<float> _cfgCameraCinematicDistance;

		private ConfigEntry<float> _cfgCameraCinematicMinDistance;

		private ConfigEntry<float> _cfgCameraCinematicMaxDistance;

		private ConfigEntry<float> _cfgCameraCinematicOrbitSpeed;

		private ConfigEntry<float> _cfgCameraCinematicHeightMultiplier;

		private ConfigEntry<bool> _cfgDebugEnabled;

		private ConfigEntry<bool> _cfgUIEnabled;

		private ConfigEntry<KeyCode> _cfgKeyToggleSpectator;

		private ConfigEntry<KeyCode> _cfgKeySwitchEnemy;

		private ConfigEntry<KeyCode> _cfgKeyToggleCameraMode;

		private bool _isSpectating;

		private SpectatorCamera _spectatorCamera;

		private EnemyTracker _enemyTracker;

		private SpectatorUI _spectatorUI;

		private SpectatorCameraMode _cameraMode;

		private Vector2 _mouseDelta;

		private bool _isRotating;

		private Camera _originalMainCamera;

		private CameraController _cameraController;

		private bool _originalCameraEnabled = true;

		private GameObject _originalCameraGameObject;

		private GameObject _playerGameObject;

		private Rigidbody _playerRigidbody;

		private bool _playerRigidbodyWasKinematic;

		private RigidbodyConstraints _playerRigidbodyOriginalConstraints;

		private GunControl _gunControl;

		private bool _gunControlWasEnabled;

		private Harmony _harmony;

		public bool IsSpectating => _isSpectating;

		public SpectatorCameraMode CameraMode => _cameraMode;

		public SpectatorCamera SpectatorCamera => _spectatorCamera;

		public EnemyTracker EnemyTracker => _enemyTracker;

		public bool DebugEnabled => _cfgDebugEnabled?.Value ?? false;

		public bool UIEnabled => _cfgUIEnabled?.Value ?? true;

		public float CameraFOV => _cfgCameraFOV?.Value ?? 60f;

		public float CameraOrbitDistance
		{
			get
			{
				return _cfgCameraOrbitDistance?.Value ?? 15f;
			}
			set
			{
				if (_cfgCameraOrbitDistance != null)
				{
					_cfgCameraOrbitDistance.Value = value;
				}
			}
		}

		public float CameraOrbitMinDistance => _cfgCameraOrbitMinDistance?.Value ?? 3f;

		public float CameraOrbitMaxDistance => _cfgCameraOrbitMaxDistance?.Value ?? 40f;

		public float CameraFollowDistance
		{
			get
			{
				return _cfgCameraFollowDistance?.Value ?? 8f;
			}
			set
			{
				if (_cfgCameraFollowDistance != null)
				{
					_cfgCameraFollowDistance.Value = value;
				}
			}
		}

		public float CameraFollowMinDistance => _cfgCameraFollowMinDistance?.Value ?? 3f;

		public float CameraFollowMaxDistance => _cfgCameraFollowMaxDistance?.Value ?? 25f;

		public float CameraFollowHeightMultiplier => _cfgCameraFollowHeightMultiplier?.Value ?? 1.2f;

		public float CameraOrbitSensitivity => _cfgCameraOrbitSensitivity?.Value ?? 1.5f;

		public float CameraZoomSensitivity => _cfgCameraZoomSensitivity?.Value ?? 5f;

		public float CameraCinematicDistance
		{
			get
			{
				return _cfgCameraCinematicDistance?.Value ?? 30f;
			}
			set
			{
				if (_cfgCameraCinematicDistance != null)
				{
					_cfgCameraCinematicDistance.Value = value;
				}
			}
		}

		public float CameraCinematicMinDistance => _cfgCameraCinematicMinDistance?.Value ?? 15f;

		public float CameraCinematicMaxDistance => _cfgCameraCinematicMaxDistance?.Value ?? 60f;

		public float CameraCinematicOrbitSpeed => _cfgCameraCinematicOrbitSpeed?.Value ?? 5f;

		public float CameraCinematicHeightMultiplier => _cfgCameraCinematicHeightMultiplier?.Value ?? 2f;

		private void Awake()
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Log.LogInfo((object)"[EnemySpectate] Initializing...");
			try
			{
				LoadConfiguration();
				_enemyTracker = new EnemyTracker();
				_spectatorUI = new SpectatorUI();
				_spectatorUI.Initialize();
				_cameraController = MonoSingleton<CameraController>.Instance;
				_originalMainCamera = Camera.main;
				if ((Object)(object)_originalMainCamera != (Object)null)
				{
					_originalCameraGameObject = ((Component)_originalMainCamera).gameObject;
					Log.LogInfo((object)("[SpectatorManager] Found original main camera: " + ((Object)_originalCameraGameObject).name));
				}
				else
				{
					Log.LogWarning((object)"[SpectatorManager] No main camera found at start!");
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[EnemySpectate] Failed to initialize: " + ex.Message));
				Log.LogError((object)ex.StackTrace);
				return;
			}
			_harmony = new Harmony("com.enemyspectate.plugin");
			try
			{
				_harmony.PatchAll(Assembly.GetExecutingAssembly());
			}
			catch (Exception ex2)
			{
				Log.LogError((object)("[EnemySpectate] Harmony patching failed: " + ex2.Message));
			}
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			Log.LogInfo((object)("[EnemySpectate] v1.0.0 loaded successfully! Config file: " + ((BaseUnityPlugin)this).Config.ConfigFilePath));
		}

		private void LoadConfiguration()
		{
			Log.LogInfo((object)"[EnemySpectate] Loading configuration...");
			_cfgCameraFOV = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "FOV", 60f, "Field of view for the spectator camera.");
			_cfgCameraOrbitDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "OrbitDistance", 15f, "Default orbit distance from the enemy.");
			_cfgCameraOrbitMinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "OrbitMinDistance", 3f, "Minimum orbit distance (zoom in limit).");
			_cfgCameraOrbitMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "OrbitMaxDistance", 40f, "Maximum orbit distance (zoom out limit).");
			_cfgCameraFollowDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "FollowDistance", 8f, "Default follow distance behind the enemy.");
			_cfgCameraFollowMinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "FollowMinDistance", 3f, "Minimum follow distance.");
			_cfgCameraFollowMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "FollowMaxDistance", 25f, "Maximum follow distance.");
			_cfgCameraFollowHeightMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "FollowHeightMultiplier", 1.2f, "Camera height multiplier based on enemy height (height * multiplier).");
			_cfgCameraOrbitSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "OrbitSensitivity", 1.5f, "Mouse rotation sensitivity for orbit mode.");
			_cfgCameraZoomSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "ZoomSensitivity", 5f, "Scroll wheel zoom sensitivity.");
			_cfgCameraCinematicDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CinematicDistance", 30f, "Default distance for cinematic mode (zoomed out to see all enemies).");
			_cfgCameraCinematicMinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CinematicMinDistance", 15f, "Minimum cinematic distance.");
			_cfgCameraCinematicMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CinematicMaxDistance", 60f, "Maximum cinematic distance.");
			_cfgCameraCinematicOrbitSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CinematicOrbitSpeed", 5f, "Auto-orbit speed for cinematic mode (degrees per second).");
			_cfgCameraCinematicHeightMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CinematicHeightMultiplier", 2f, "Camera height multiplier for cinematic mode.");
			_cfgDebugEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Enabled", false, "Enable debug logging.");
			_cfgUIEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "Enabled", true, "Show the spectator UI overlay.");
			_cfgKeyToggleSpectator = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ToggleSpectator", (KeyCode)286, "Key to toggle spectator mode.");
			_cfgKeySwitchEnemy = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "SwitchEnemy", (KeyCode)32, "Key to switch to the next enemy.");
			_cfgKeyToggleCameraMode = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ToggleCameraMode", (KeyCode)99, "Key to toggle between Orbit, Follow, and Cinematic camera modes.");
			Log.LogInfo((object)"[EnemySpectate] Configuration loaded.");
		}

		private void Start()
		{
			if ((Object)(object)_cameraController == (Object)null)
			{
				_cameraController = MonoSingleton<CameraController>.Instance;
			}
			FindPlayer();
		}

		private void FindPlayer()
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			GameObject[] array = GameObject.FindGameObjectsWithTag("Player");
			if (array.Length != 0)
			{
				_playerGameObject = array[0];
				Log.LogInfo((object)("[EnemySpectate] Found player via tag 'Player': " + ((Object)_playerGameObject).name));
			}
			if ((Object)(object)_playerGameObject == (Object)null)
			{
				GunControl instance = MonoSingleton<GunControl>.Instance;
				GameObject val = ((instance != null) ? ((Component)instance).gameObject : null);
				if ((Object)(object)val != (Object)null)
				{
					_playerGameObject = val;
					Log.LogInfo((object)("[EnemySpectate] Found player via GunControl: " + ((Object)_playerGameObject).name));
				}
			}
			if ((Object)(object)_playerGameObject != (Object)null)
			{
				_playerRigidbody = _playerGameObject.GetComponent<Rigidbody>();
				if ((Object)(object)_playerRigidbody != (Object)null)
				{
					_playerRigidbodyWasKinematic = _playerRigidbody.isKinematic;
					_playerRigidbodyOriginalConstraints = _playerRigidbody.constraints;
					Log.LogInfo((object)$"[EnemySpectate] Cached player Rigidbody: isKinematic={_playerRigidbodyWasKinematic}, constraints={_playerRigidbodyOriginalConstraints}");
				}
				_gunControl = MonoSingleton<GunControl>.Instance;
				if ((Object)(object)_gunControl != (Object)null)
				{
					_gunControlWasEnabled = ((Behaviour)_gunControl).enabled;
					Log.LogInfo((object)$"[EnemySpectate] Cached GunControl: enabled={_gunControlWasEnabled}");
				}
			}
			else
			{
				Log.LogWarning((object)"[EnemySpectate] Could not find player GameObject!");
			}
		}

		private void Update()
		{
			if (!_isSpectating)
			{
				HandleToggleInput();
				return;
			}
			HandleSpectatorInput();
			_enemyTracker.Update();
			_spectatorCamera?.UpdateCamera();
		}

		private void LateUpdate()
		{
			if (_isSpectating && _spectatorCamera != null)
			{
				_spectatorCamera.LateUpdateCamera();
			}
		}

		private void OnGUI()
		{
			if (_isSpectating && UIEnabled)
			{
				_spectatorUI?.OnGUI();
			}
		}

		private void HandleToggleInput()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<KeyCode> cfgKeyToggleSpectator = _cfgKeyToggleSpectator;
			if (Input.GetKeyDown((KeyCode)((cfgKeyToggleSpectator == null) ? 286 : ((int)cfgKeyToggleSpectator.Value))))
			{
				Log.LogInfo((object)"[EnemySpectate] Toggle key pressed - toggling spectator mode");
				ToggleSpectatorMode();
			}
		}

		private void HandleSpectatorInput()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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)
			ConfigEntry<KeyCode> cfgKeySwitchEnemy = _cfgKeySwitchEnemy;
			if (Input.GetKeyDown((KeyCode)((cfgKeySwitchEnemy == null) ? 32 : ((int)cfgKeySwitchEnemy.Value))))
			{
				Log.LogInfo((object)"[EnemySpectate] Switch enemy key pressed");
				_enemyTracker.SelectNextEnemy();
			}
			ConfigEntry<KeyCode> cfgKeyToggleCameraMode = _cfgKeyToggleCameraMode;
			if (Input.GetKeyDown((KeyCode)((cfgKeyToggleCameraMode == null) ? 99 : ((int)cfgKeyToggleCameraMode.Value))))
			{
				ToggleCameraMode();
			}
			if (Input.GetMouseButtonDown(2))
			{
				_isRotating = true;
				Cursor.lockState = (CursorLockMode)1;
				Cursor.visible = false;
			}
			else if (Input.GetMouseButtonUp(2))
			{
				_isRotating = false;
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
			if (_isRotating)
			{
				_mouseDelta = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
				_spectatorCamera?.AddRotationInput(_mouseDelta);
			}
			float axis = Input.GetAxis("Mouse ScrollWheel");
			if (axis != 0f)
			{
				_spectatorCamera?.AddScrollInput(axis);
			}
			ConfigEntry<KeyCode> cfgKeyToggleSpectator = _cfgKeyToggleSpectator;
			if (Input.GetKeyDown((KeyCode)((cfgKeyToggleSpectator == null) ? 286 : ((int)cfgKeyToggleSpectator.Value))))
			{
				Log.LogInfo((object)"[EnemySpectate] Toggle key pressed - toggling spectator mode");
				ToggleSpectatorMode();
			}
		}

		public void ToggleSpectatorMode()
		{
			if (!_isSpectating)
			{
				EnableSpectatorMode();
			}
			else
			{
				DisableSpectatorMode();
			}
		}

		private void EnableSpectatorMode()
		{
			Log.LogInfo((object)"[EnemySpectate] Enabling spectator mode...");
			_originalMainCamera = Camera.main;
			if ((Object)(object)_originalMainCamera != (Object)null)
			{
				_originalCameraGameObject = ((Component)_originalMainCamera).gameObject;
				_originalCameraEnabled = ((Behaviour)_originalMainCamera).enabled;
				Log.LogInfo((object)$"[EnemySpectate] Stored original camera state: enabled={_originalCameraEnabled}");
			}
			else
			{
				Log.LogWarning((object)"[EnemySpectate] No main camera found to disable!");
			}
			FreezePlayer();
			_enemyTracker.RefreshEnemyList();
			if ((Object)(object)_enemyTracker.CurrentEnemy == (Object)null)
			{
				Log.LogWarning((object)"[EnemySpectate] No enemies available to spectate!");
				UnfreezePlayer();
				return;
			}
			_spectatorCamera = new SpectatorCamera();
			_spectatorCamera.Initialize(this, _enemyTracker.CurrentEnemy);
			_spectatorCamera.PrepareForSpectating();
			if ((Object)(object)_cameraController != (Object)null)
			{
				((Behaviour)_cameraController).enabled = false;
				Log.LogInfo((object)"[EnemySpectate] CameraController disabled");
			}
			_isSpectating = true;
			Log.LogInfo((object)("[EnemySpectate] Spectator mode enabled. Target: " + ((Object)_enemyTracker.CurrentEnemy).name));
		}

		private void DisableSpectatorMode()
		{
			//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)
			Log.LogInfo((object)"[EnemySpectate] Disabling spectator mode...");
			_isSpectating = false;
			_isRotating = false;
			_mouseDelta = Vector2.zero;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
			UnfreezePlayer();
			if (_spectatorCamera != null)
			{
				try
				{
					_spectatorCamera.RestoreOriginalCamera();
					Log.LogInfo((object)"[EnemySpectate] Original camera and player arms restored");
				}
				catch
				{
				}
			}
			if ((Object)(object)_cameraController != (Object)null)
			{
				try
				{
					((Behaviour)_cameraController).enabled = true;
					Log.LogInfo((object)"[EnemySpectate] CameraController re-enabled");
				}
				catch
				{
				}
			}
			if (_spectatorCamera != null)
			{
				try
				{
					_spectatorCamera.Destroy();
					_spectatorCamera = null;
				}
				catch
				{
				}
			}
			Log.LogInfo((object)"[EnemySpectate] Spectator mode disabled");
		}

		private void FreezePlayer()
		{
			//IL_006e: 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)
			if ((Object)(object)_playerGameObject == (Object)null)
			{
				FindPlayer();
			}
			if ((Object)(object)_playerGameObject == (Object)null)
			{
				Log.LogWarning((object)"[EnemySpectate] Cannot freeze player - player not found!");
				return;
			}
			Log.LogInfo((object)"[EnemySpectate] Freezing player...");
			if ((Object)(object)_playerRigidbody != (Object)null)
			{
				_playerRigidbody.isKinematic = true;
				_playerRigidbody.constraints = (RigidbodyConstraints)126;
				_playerRigidbody.velocity = Vector3.zero;
				_playerRigidbody.angularVelocity = Vector3.zero;
				Log.LogInfo((object)"[EnemySpectate] Player Rigidbody frozen (kinematic + FreezeAll)");
			}
			if ((Object)(object)_gunControl != (Object)null)
			{
				((Behaviour)_gunControl).enabled = false;
				Log.LogInfo((object)"[EnemySpectate] GunControl disabled (no shooting/weapon switching)");
			}
			if ((Object)(object)_cameraController != (Object)null)
			{
				((Behaviour)_cameraController).enabled = false;
				Log.LogInfo((object)"[EnemySpectate] CameraController disabled (no camera movement)");
			}
		}

		private void UnfreezePlayer()
		{
			//IL_0035: 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)
			Log.LogInfo((object)"[EnemySpectate] Unfreezing player...");
			if ((Object)(object)_playerRigidbody != (Object)null)
			{
				try
				{
					_playerRigidbody.isKinematic = _playerRigidbodyWasKinematic;
					_playerRigidbody.constraints = _playerRigidbodyOriginalConstraints;
					Log.LogInfo((object)$"[EnemySpectate] Player Rigidbody restored (kinematic={_playerRigidbodyWasKinematic}, constraints={_playerRigidbodyOriginalConstraints})");
				}
				catch
				{
				}
			}
			if ((Object)(object)_gunControl != (Object)null)
			{
				try
				{
					((Behaviour)_gunControl).enabled = _gunControlWasEnabled;
					Log.LogInfo((object)$"[EnemySpectate] GunControl re-enabled (enabled={_gunControlWasEnabled})");
				}
				catch
				{
				}
			}
			if ((Object)(object)_cameraController != (Object)null)
			{
				try
				{
					((Behaviour)_cameraController).enabled = true;
					Log.LogInfo((object)"[EnemySpectate] CameraController re-enabled");
				}
				catch
				{
				}
			}
		}

		private void ToggleCameraMode()
		{
			_cameraMode = _cameraMode switch
			{
				SpectatorCameraMode.Orbit => SpectatorCameraMode.Follow, 
				SpectatorCameraMode.Follow => SpectatorCameraMode.Cinematic, 
				SpectatorCameraMode.Cinematic => SpectatorCameraMode.Orbit, 
				_ => SpectatorCameraMode.Orbit, 
			};
			Log.LogInfo((object)$"[EnemySpectate] Camera mode changed to: {_cameraMode}");
			_spectatorCamera?.OnCameraModeChanged(_cameraMode);
		}

		public void OnEnemyChanged(EnemyIdentifier newEnemy)
		{
			Log.LogInfo((object)("[EnemySpectate] Enemy changed to: " + (((newEnemy != null) ? ((Object)newEnemy).name : null) ?? "null")));
			_spectatorCamera?.SetTarget(newEnemy);
			_spectatorUI?.OnEnemyChanged(newEnemy);
		}

		public void OnNoEnemiesAvailable()
		{
			Log.LogWarning((object)"[EnemySpectate] No enemies available!");
			_spectatorUI?.ShowNoEnemiesMessage();
		}

		private void OnDestroy()
		{
			Log.LogInfo((object)"[EnemySpectate] OnDestroy called");
			_isSpectating = false;
			_isRotating = false;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
			UnfreezePlayer();
			if ((Object)(object)_originalMainCamera != (Object)null)
			{
				try
				{
					((Behaviour)_originalMainCamera).enabled = _originalCameraEnabled;
					((Component)_originalMainCamera).tag = "MainCamera";
				}
				catch
				{
				}
			}
			if ((Object)(object)_cameraController != (Object)null)
			{
				try
				{
					((Behaviour)_cameraController).enabled = true;
				}
				catch
				{
				}
			}
			if (_spectatorCamera != null)
			{
				try
				{
					_spectatorCamera.Destroy();
					_spectatorCamera = null;
				}
				catch
				{
				}
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Log.LogInfo((object)"[EnemySpectate] Unloaded.");
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.enemyspectate.plugin";

		public const string PLUGIN_NAME = "EnemySpectate";

		public const string PLUGIN_VERSION = "1.0.0";
	}
	public enum SpectatorCameraMode
	{
		Orbit,
		Follow,
		Cinematic
	}
	public class EnemyTracker
	{
		private List<EnemyIdentifier> _enemies = new List<EnemyIdentifier>();

		private int _currentEnemyIndex = -1;

		private float _lastRefreshTime;

		private const float REFRESH_INTERVAL = 1f;

		private static ManualLogSource Log => EnemySpectatePlugin.Log;

		public EnemyIdentifier CurrentEnemy
		{
			get
			{
				if (_currentEnemyIndex < 0 || _currentEnemyIndex >= _enemies.Count)
				{
					return null;
				}
				return _enemies[_currentEnemyIndex];
			}
		}

		public int CurrentEnemyIndex => _currentEnemyIndex;

		public int EnemyCount => _enemies.Count;

		public IReadOnlyList<EnemyIdentifier> Enemies => _enemies;

		public void Update()
		{
			if (Time.time - _lastRefreshTime > 1f)
			{
				RefreshEnemyList();
			}
			if ((Object)(object)CurrentEnemy == (Object)null || !IsEnemyValid(CurrentEnemy))
			{
				Log.LogInfo((object)"[EnemyTracker] Current enemy invalid, finding replacement...");
				SelectValidEnemy();
			}
		}

		public void RefreshEnemyList()
		{
			_lastRefreshTime = Time.time;
			EnemyIdentifier[] array = Object.FindObjectsByType<EnemyIdentifier>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			List<EnemyIdentifier> list = new List<EnemyIdentifier>();
			EnemyIdentifier[] array2 = array;
			foreach (EnemyIdentifier val in array2)
			{
				if (IsEnemyValid(val))
				{
					list.Add(val);
				}
			}
			bool num = (Object)(object)CurrentEnemy != (Object)null && list.Contains(CurrentEnemy);
			_enemies = list.OrderBy((EnemyIdentifier e) => ((Object)((Component)e).gameObject).GetInstanceID()).ToList();
			Log.LogDebug((object)$"[EnemyTracker] Refreshed enemy list: {_enemies.Count} enemies found");
			if (!num)
			{
				SelectValidEnemy();
			}
		}

		private bool IsEnemyValid(EnemyIdentifier enemy)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemy == (Object)null)
			{
				return false;
			}
			if (!((Component)enemy).gameObject.activeInHierarchy)
			{
				return false;
			}
			Scene scene = ((Component)enemy).gameObject.scene;
			if (!((Scene)(ref scene)).isLoaded)
			{
				return false;
			}
			if ((Object)(object)((Component)enemy).transform == (Object)null)
			{
				return false;
			}
			try
			{
				FieldInfo field = typeof(EnemyIdentifier).GetField("dead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null && (bool)(field.GetValue(enemy) ?? ((object)false)))
				{
					return false;
				}
			}
			catch
			{
			}
			return true;
		}

		public void SelectNextEnemy()
		{
			if (_enemies.Count == 0)
			{
				RefreshEnemyList();
				if (_enemies.Count == 0)
				{
					EnemySpectatePlugin.Instance.OnNoEnemiesAvailable();
					return;
				}
			}
			_currentEnemyIndex = (_currentEnemyIndex + 1) % _enemies.Count;
			SelectValidEnemy();
		}

		public void SelectPreviousEnemy()
		{
			if (_enemies.Count == 0)
			{
				RefreshEnemyList();
				if (_enemies.Count == 0)
				{
					EnemySpectatePlugin.Instance.OnNoEnemiesAvailable();
					return;
				}
			}
			_currentEnemyIndex = (_currentEnemyIndex - 1 + _enemies.Count) % _enemies.Count;
			SelectValidEnemy();
		}

		private void SelectValidEnemy()
		{
			if (_enemies.Count == 0)
			{
				_currentEnemyIndex = -1;
				EnemySpectatePlugin.Instance.OnEnemyChanged(null);
				EnemySpectatePlugin.Instance.OnNoEnemiesAvailable();
				return;
			}
			if (_currentEnemyIndex >= 0 && _currentEnemyIndex < _enemies.Count)
			{
				EnemyIdentifier val = _enemies[_currentEnemyIndex];
				if (IsEnemyValid(val))
				{
					EnemySpectatePlugin.Instance.OnEnemyChanged(val);
					return;
				}
			}
			for (int i = 0; i < _enemies.Count; i++)
			{
				if (IsEnemyValid(_enemies[i]))
				{
					_currentEnemyIndex = i;
					EnemySpectatePlugin.Instance.OnEnemyChanged(_enemies[i]);
					return;
				}
			}
			_currentEnemyIndex = -1;
			EnemySpectatePlugin.Instance.OnEnemyChanged(null);
			EnemySpectatePlugin.Instance.OnNoEnemiesAvailable();
		}

		public string GetEnemyDisplayName(EnemyIdentifier enemy)
		{
			if ((Object)(object)enemy == (Object)null)
			{
				return "None";
			}
			return ((Object)((Component)enemy).gameObject).name.Replace("(Clone)", "").Trim();
		}
	}
	public class SpectatorCamera
	{
		private GameObject _gameObject;

		private Camera _camera;

		private EnemyIdentifier _target;

		private EnemySpectatePlugin _plugin;

		private Vector3 _currentPosition;

		private Quaternion _currentRotation;

		private Vector3 _velocity = Vector3.zero;

		private Vector2 _rotationInput = Vector2.zero;

		private Camera _originalCamera;

		private int _originalCullingMask;

		private AudioListener _originalAudioListener;

		private bool _originalAudioListenerEnabled;

		private AudioListener _spectatorAudioListener;

		private List<Renderer> _hiddenRenderers = new List<Renderer>();

		private float _cinematicAngle;

		private Vector3 _cinematicCenter = Vector3.zero;

		private Vector3 _orbitOffset = Vector3.up * 2f;

		private Vector3 _orbitAngles = new Vector3(15f, 0f, 0f);

		private static ManualLogSource Log => EnemySpectatePlugin.Log;

		public Camera CameraComponent => _camera;

		public EnemyIdentifier Target => _target;

		public void Initialize(EnemySpectatePlugin plugin, EnemyIdentifier target)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: 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)
			_plugin = plugin;
			_target = target;
			_gameObject = new GameObject("SpectatorCamera");
			_camera = _gameObject.AddComponent<Camera>();
			_camera.fieldOfView = _plugin.CameraFOV;
			_camera.nearClipPlane = 0.1f;
			_camera.farClipPlane = 1000f;
			_camera.depth = 100f;
			_camera.clearFlags = (CameraClearFlags)1;
			_originalCamera = Camera.main;
			if ((Object)(object)_originalCamera != (Object)null)
			{
				_originalCullingMask = _originalCamera.cullingMask;
				_camera.cullingMask = _originalCullingMask;
				Log.LogInfo((object)$"[SpectatorCamera] Stored original camera culling mask: {_originalCullingMask}");
			}
			Camera originalCamera = _originalCamera;
			_originalAudioListener = ((originalCamera != null) ? ((Component)originalCamera).GetComponent<AudioListener>() : null);
			if ((Object)(object)_originalAudioListener == (Object)null)
			{
				AudioListener[] source = Resources.FindObjectsOfTypeAll<AudioListener>();
				_originalAudioListener = ((IEnumerable<AudioListener>)source).FirstOrDefault((Func<AudioListener, bool>)((AudioListener l) => ((Behaviour)l).isActiveAndEnabled));
			}
			if ((Object)(object)_originalAudioListener != (Object)null)
			{
				_originalAudioListenerEnabled = ((Behaviour)_originalAudioListener).enabled;
				((Behaviour)_originalAudioListener).enabled = false;
				Log.LogInfo((object)("[SpectatorCamera] Disabled original AudioListener on " + ((Object)((Component)_originalAudioListener).gameObject).name));
			}
			_spectatorAudioListener = _gameObject.AddComponent<AudioListener>();
			Log.LogInfo((object)"[SpectatorCamera] Added AudioListener to spectator camera - audio will now be heard from camera position");
			Object.DontDestroyOnLoad((Object)(object)_gameObject);
			if ((Object)(object)_target != (Object)null)
			{
				UpdateCameraPosition();
				_currentPosition = _gameObject.transform.position;
				_currentRotation = _gameObject.transform.rotation;
			}
			Log.LogInfo((object)("[SpectatorCamera] Initialized with target: " + (((target != null) ? ((Object)target).name : null) ?? "null")));
			Log.LogDebug((object)$"[SpectatorCamera] FOV={_camera.fieldOfView}, OrbitDist={_plugin.CameraOrbitDistance}, FollowDist={_plugin.CameraFollowDistance}");
		}

		public void Destroy()
		{
			Log.LogInfo((object)"[SpectatorCamera] Destroyed");
			RestoreOriginalCamera();
			if ((Object)(object)_gameObject != (Object)null)
			{
				try
				{
					Object.Destroy((Object)(object)_gameObject);
					_gameObject = null;
					_camera = null;
				}
				catch
				{
				}
			}
		}

		public void SetTarget(EnemyIdentifier newTarget)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			_target = newTarget;
			_rotationInput = Vector2.zero;
			if ((Object)(object)_target != (Object)null)
			{
				_orbitAngles = new Vector3(15f, 0f, 0f);
				UpdateCameraPosition();
				_currentPosition = _gameObject.transform.position;
				_currentRotation = _gameObject.transform.rotation;
			}
			Log.LogInfo((object)("[SpectatorCamera] Target changed to: " + (((newTarget != null) ? ((Object)newTarget).name : null) ?? "null")));
		}

		public void OnCameraModeChanged(SpectatorCameraMode mode)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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)
			Log.LogInfo((object)$"[SpectatorCamera] Mode changed to: {mode}");
			_rotationInput = Vector2.zero;
			if (mode == SpectatorCameraMode.Cinematic)
			{
				_cinematicAngle = 0f;
				_cinematicCenter = Vector3.zero;
			}
			if ((Object)(object)_target != (Object)null)
			{
				UpdateCameraPosition();
				_currentPosition = _gameObject.transform.position;
				_currentRotation = _gameObject.transform.rotation;
			}
		}

		public void AddRotationInput(Vector2 delta)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			_rotationInput += delta;
		}

		public void AddScrollInput(float scroll)
		{
			if (_plugin.CameraMode == SpectatorCameraMode.Orbit)
			{
				float cameraOrbitDistance = _plugin.CameraOrbitDistance;
				float cameraOrbitMinDistance = _plugin.CameraOrbitMinDistance;
				float cameraOrbitMaxDistance = _plugin.CameraOrbitMaxDistance;
				float cameraZoomSensitivity = _plugin.CameraZoomSensitivity;
				cameraOrbitDistance -= scroll * cameraZoomSensitivity;
				cameraOrbitDistance = Mathf.Clamp(cameraOrbitDistance, cameraOrbitMinDistance, cameraOrbitMaxDistance);
				_plugin.CameraOrbitDistance = cameraOrbitDistance;
			}
			else if (_plugin.CameraMode == SpectatorCameraMode.Follow)
			{
				float cameraFollowDistance = _plugin.CameraFollowDistance;
				float cameraFollowMinDistance = _plugin.CameraFollowMinDistance;
				float cameraFollowMaxDistance = _plugin.CameraFollowMaxDistance;
				float cameraZoomSensitivity2 = _plugin.CameraZoomSensitivity;
				cameraFollowDistance -= scroll * cameraZoomSensitivity2;
				cameraFollowDistance = Mathf.Clamp(cameraFollowDistance, cameraFollowMinDistance, cameraFollowMaxDistance);
				_plugin.CameraFollowDistance = cameraFollowDistance;
			}
			else
			{
				float cameraCinematicDistance = _plugin.CameraCinematicDistance;
				float cameraCinematicMinDistance = _plugin.CameraCinematicMinDistance;
				float cameraCinematicMaxDistance = _plugin.CameraCinematicMaxDistance;
				float cameraZoomSensitivity3 = _plugin.CameraZoomSensitivity;
				cameraCinematicDistance -= scroll * cameraZoomSensitivity3;
				cameraCinematicDistance = Mathf.Clamp(cameraCinematicDistance, cameraCinematicMinDistance, cameraCinematicMaxDistance);
				_plugin.CameraCinematicDistance = cameraCinematicDistance;
			}
		}

		public void UpdateCamera()
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			if (_plugin.CameraMode != SpectatorCameraMode.Cinematic && ((Object)(object)_target == (Object)null || !((Component)_target).gameObject.activeInHierarchy))
			{
				return;
			}
			if (((Vector2)(ref _rotationInput)).sqrMagnitude > 0.0001f)
			{
				if (_plugin.CameraMode == SpectatorCameraMode.Orbit)
				{
					_orbitAngles.y += _rotationInput.x * GetOrbitSensitivity();
					_orbitAngles.x -= _rotationInput.y * GetOrbitSensitivity();
					_orbitAngles.x = Mathf.Clamp(_orbitAngles.x, -80f, 80f);
				}
				_rotationInput = Vector2.zero;
			}
			Vector3 position;
			Quaternion rotation;
			if (_plugin.CameraMode == SpectatorCameraMode.Orbit)
			{
				CalculateOrbitTransform(out position, out rotation);
			}
			else if (_plugin.CameraMode == SpectatorCameraMode.Follow)
			{
				CalculateFollowTransform(out position, out rotation);
			}
			else
			{
				CalculateCinematicTransform(out position, out rotation);
			}
			_currentPosition = Vector3.SmoothDamp(_currentPosition, position, ref _velocity, 0.1f);
			_currentRotation = Quaternion.Slerp(_currentRotation, rotation, Time.deltaTime * GetFollowSmoothing());
			_gameObject.transform.SetPositionAndRotation(_currentPosition, _currentRotation);
		}

		public void LateUpdateCamera()
		{
		}

		private float GetOrbitSensitivity()
		{
			return _plugin.CameraOrbitSensitivity;
		}

		private float GetFollowSmoothing()
		{
			return 10f;
		}

		private float GetCinematicOrbitSpeed()
		{
			return _plugin.CameraCinematicOrbitSpeed;
		}

		private float GetCinematicDistance()
		{
			return _plugin.CameraCinematicDistance;
		}

		private float GetCinematicMinDistance()
		{
			return _plugin.CameraCinematicMinDistance;
		}

		private float GetCinematicMaxDistance()
		{
			return _plugin.CameraCinematicMaxDistance;
		}

		private float GetCinematicHeightMultiplier()
		{
			return _plugin.CameraCinematicHeightMultiplier;
		}

		private void CalculateOrbitTransform(out Vector3 position, out Quaternion rotation)
		{
			//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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//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_0081: 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_0088: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_target == (Object)null)
			{
				position = _gameObject.transform.position;
				rotation = _gameObject.transform.rotation;
				return;
			}
			Vector3 targetPosition = GetTargetPosition();
			float cameraOrbitDistance = _plugin.CameraOrbitDistance;
			Quaternion val = Quaternion.Euler(_orbitAngles.x, _orbitAngles.y, 0f);
			Vector3 val2 = val * (Vector3.back * cameraOrbitDistance);
			Vector3 val3 = targetPosition + _orbitOffset + val2;
			Vector3 val4 = val3 - targetPosition;
			Vector3 normalized = ((Vector3)(ref val4)).normalized;
			float num = Vector3.Distance(targetPosition, val3);
			RaycastHit val5 = default(RaycastHit);
			if (Physics.SphereCast(targetPosition + _orbitOffset, 0.5f, normalized, ref val5, num, -1, (QueryTriggerInteraction)1))
			{
				float num2 = ((RaycastHit)(ref val5)).distance - 0.5f;
				if (num2 > 1f)
				{
					val3 = targetPosition + _orbitOffset + normalized * num2;
				}
			}
			position = val3;
			rotation = val;
		}

		private void CalculateFollowTransform(out Vector3 position, out Quaternion rotation)
		{
			//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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00a9: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_target == (Object)null)
			{
				position = _gameObject.transform.position;
				rotation = _gameObject.transform.rotation;
				return;
			}
			Transform transform = ((Component)_target).transform;
			Vector3 position2 = transform.position;
			float enemyHeight = GetEnemyHeight();
			float num = enemyHeight * GetFollowHeightMultiplier();
			Vector3 forward = transform.forward;
			Vector3 up = transform.up;
			Vector3 val = position2 - forward * GetFollowDistance() + up * num;
			Vector3 val2 = val - position2;
			Vector3 normalized = ((Vector3)(ref val2)).normalized;
			float num2 = Vector3.Distance(position2, val);
			RaycastHit val3 = default(RaycastHit);
			if (Physics.SphereCast(position2 + Vector3.up * 0.5f, 0.5f, normalized, ref val3, num2, -1, (QueryTriggerInteraction)1))
			{
				float num3 = ((RaycastHit)(ref val3)).distance - 0.5f;
				if (num3 > 1f)
				{
					val = position2 + normalized * num3;
				}
			}
			position = val;
			Vector3 val4 = position2 + up * (enemyHeight * 0.5f);
			rotation = Quaternion.LookRotation(val4 - position, up);
		}

		private float GetEnemyHeight()
		{
			//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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_target == (Object)null)
			{
				return 2f;
			}
			Collider component = ((Component)_target).GetComponent<Collider>();
			Bounds bounds;
			if ((Object)(object)component != (Object)null)
			{
				bounds = component.bounds;
				return Mathf.Max(((Bounds)(ref bounds)).size.y, 0.5f);
			}
			Renderer componentInChildren = ((Component)_target).GetComponentInChildren<Renderer>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				bounds = componentInChildren.bounds;
				return Mathf.Max(((Bounds)(ref bounds)).size.y, 0.5f);
			}
			return 2f;
		}

		private float GetFollowHeightMultiplier()
		{
			return _plugin.CameraFollowHeightMultiplier;
		}

		private float GetFollowDistance()
		{
			return _plugin.CameraFollowDistance;
		}

		private void CalculateCinematicTransform(out Vector3 position, out Quaternion rotation)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: 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_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: 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_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			IReadOnlyList<EnemyIdentifier> readOnlyList = _plugin.EnemyTracker?.Enemies;
			if (readOnlyList == null || readOnlyList.Count == 0)
			{
				position = _gameObject.transform.position;
				rotation = _gameObject.transform.rotation;
				return;
			}
			Vector3 val = Vector3.zero;
			float num = 0f;
			float num2 = float.MaxValue;
			float num3 = float.MinValue;
			int num4 = 0;
			foreach (EnemyIdentifier item in readOnlyList)
			{
				if ((Object)(object)item != (Object)null && ((Component)item).gameObject.activeInHierarchy)
				{
					val += ((Component)item).transform.position;
					Collider component = ((Component)item).GetComponent<Collider>();
					if ((Object)(object)component != (Object)null)
					{
						float num5 = num;
						Bounds bounds = component.bounds;
						num = Mathf.Max(num5, ((Bounds)(ref bounds)).size.y);
						float num6 = num2;
						bounds = component.bounds;
						num2 = Mathf.Min(num6, ((Bounds)(ref bounds)).min.y);
						float num7 = num3;
						bounds = component.bounds;
						num3 = Mathf.Max(num7, ((Bounds)(ref bounds)).max.y);
					}
					num4++;
				}
			}
			if (num4 == 0)
			{
				position = _gameObject.transform.position;
				rotation = _gameObject.transform.rotation;
				return;
			}
			val /= (float)num4;
			_cinematicCenter = Vector3.Lerp(_cinematicCenter, val, Time.deltaTime * 10f);
			float cinematicOrbitSpeed = GetCinematicOrbitSpeed();
			_cinematicAngle += cinematicOrbitSpeed * Time.deltaTime;
			if (_cinematicAngle >= 360f)
			{
				_cinematicAngle -= 360f;
			}
			float cinematicDistance = GetCinematicDistance();
			float cinematicHeightMultiplier = GetCinematicHeightMultiplier();
			float num8 = (num2 + num3) * 0.5f;
			float num9 = (num3 - num2) * cinematicHeightMultiplier;
			float num10 = _cinematicCenter.y + num9;
			Vector3 val2 = Quaternion.Euler(0f, _cinematicAngle, 0f) * (Vector3.back * cinematicDistance);
			Vector3 val3 = new Vector3(_cinematicCenter.x, num10, _cinematicCenter.z) + val2;
			Vector3 val4 = val3 - new Vector3(_cinematicCenter.x, num10, _cinematicCenter.z);
			Vector3 normalized = ((Vector3)(ref val4)).normalized;
			float num11 = Vector3.Distance(new Vector3(_cinematicCenter.x, num10, _cinematicCenter.z), val3);
			RaycastHit val5 = default(RaycastHit);
			if (Physics.SphereCast(new Vector3(_cinematicCenter.x, num10, _cinematicCenter.z) + Vector3.up * 0.5f, 0.5f, normalized, ref val5, num11, -1, (QueryTriggerInteraction)1))
			{
				float num12 = ((RaycastHit)(ref val5)).distance - 0.5f;
				if (num12 > 1f)
				{
					val3 = new Vector3(_cinematicCenter.x, num10, _cinematicCenter.z) + normalized * num12;
				}
			}
			position = val3;
			Vector3 val6 = default(Vector3);
			((Vector3)(ref val6))..ctor(_cinematicCenter.x, num8, _cinematicCenter.z);
			rotation = Quaternion.LookRotation(val6 - position, Vector3.up);
		}

		private Vector3 GetTargetPosition()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_target == (Object)null)
			{
				return _gameObject.transform.position;
			}
			return ((Component)_target).transform.position + _orbitOffset;
		}

		private void UpdateCameraPosition()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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)
			if (!((Object)(object)_target == (Object)null))
			{
				Transform transform = ((Component)_target).transform;
				Vector3 position = transform.position;
				if (_plugin.CameraMode == SpectatorCameraMode.Orbit)
				{
					Quaternion val = Quaternion.Euler(_orbitAngles.x, _orbitAngles.y, 0f);
					float cameraOrbitDistance = _plugin.CameraOrbitDistance;
					Vector3 val2 = val * (Vector3.back * cameraOrbitDistance);
					_gameObject.transform.SetPositionAndRotation(position + _orbitOffset + val2, val);
				}
				else
				{
					float enemyHeight = GetEnemyHeight();
					float num = enemyHeight * GetFollowHeightMultiplier();
					Vector3 forward = transform.forward;
					Vector3 up = transform.up;
					Vector3 val3 = position - forward * GetFollowDistance() + up * num;
					Quaternion val4 = Quaternion.LookRotation(position + up * (enemyHeight * 0.5f) - val3, up);
					_gameObject.transform.SetPositionAndRotation(val3, val4);
				}
			}
		}

		public void PrepareForSpectating()
		{
			Log.LogInfo((object)"[SpectatorCamera] Preparing for spectating - hiding original camera and player arms");
			if ((Object)(object)_originalCamera != (Object)null)
			{
				try
				{
					_originalCamera.cullingMask = 0;
					Log.LogInfo((object)"[SpectatorCamera] Original camera culling mask set to 0 (renders nothing)");
				}
				catch
				{
				}
			}
			HidePlayerArmRenderers();
		}

		public void RestoreOriginalCamera()
		{
			Log.LogInfo((object)"[SpectatorCamera] Restoring original camera and player arms");
			if ((Object)(object)_originalCamera != (Object)null)
			{
				try
				{
					_originalCamera.cullingMask = _originalCullingMask;
					Log.LogInfo((object)$"[SpectatorCamera] Original camera culling mask restored to {_originalCullingMask}");
				}
				catch
				{
				}
			}
			if ((Object)(object)_spectatorAudioListener != (Object)null)
			{
				try
				{
					Object.Destroy((Object)(object)_spectatorAudioListener);
					_spectatorAudioListener = null;
					Log.LogInfo((object)"[SpectatorCamera] Removed spectator AudioListener");
				}
				catch
				{
				}
			}
			if ((Object)(object)_originalAudioListener != (Object)null)
			{
				try
				{
					((Behaviour)_originalAudioListener).enabled = _originalAudioListenerEnabled;
					Log.LogInfo((object)("[SpectatorCamera] Original AudioListener re-enabled on " + ((Object)((Component)_originalAudioListener).gameObject).name));
				}
				catch
				{
				}
			}
			ShowPlayerArmRenderers();
		}

		private void HidePlayerArmRenderers()
		{
			_hiddenRenderers.Clear();
			try
			{
				GunControl instance = MonoSingleton<GunControl>.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					List<GameObject> list = new List<GameObject>();
					if ((Object)(object)instance.currentWeapon != (Object)null)
					{
						list.Add(instance.currentWeapon);
						Log.LogDebug((object)("[SpectatorCamera] Found currentWeapon: " + ((Object)instance.currentWeapon).name));
					}
					if (instance.allWeapons != null)
					{
						foreach (GameObject allWeapon in instance.allWeapons)
						{
							if ((Object)(object)allWeapon != (Object)null && !list.Contains(allWeapon))
							{
								list.Add(allWeapon);
								Log.LogDebug((object)("[SpectatorCamera] Found weapon: " + ((Object)allWeapon).name));
							}
						}
					}
					foreach (GameObject item in list)
					{
						Renderer[] componentsInChildren = item.GetComponentsInChildren<Renderer>(true);
						foreach (Renderer val in componentsInChildren)
						{
							if ((Object)(object)val != (Object)null && val.enabled)
							{
								val.enabled = false;
								_hiddenRenderers.Add(val);
								Log.LogDebug((object)("[SpectatorCamera] Hidden renderer: " + ((Object)((Component)val).gameObject).name + " (" + ((object)val).GetType().Name + ")"));
							}
						}
					}
					Log.LogInfo((object)$"[SpectatorCamera] Hidden {_hiddenRenderers.Count} player arm/weapon renderers via GunControl");
				}
				else
				{
					Log.LogWarning((object)"[SpectatorCamera] GunControl.Instance is null - using fallback search");
					HidePlayerArmRenderersFallback();
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[SpectatorCamera] Failed to hide arm renderers via GunControl: " + ex.Message));
				try
				{
					HidePlayerArmRenderersFallback();
				}
				catch
				{
				}
			}
		}

		private void HidePlayerArmRenderersFallback()
		{
			string[] source = new string[10] { "arm", "weapon", "fist", "gun", "firstperson", "fp_", "v1_arm", "player_arm", "v1model", "playermodel" };
			try
			{
				Renderer[] array = Object.FindObjectsOfType<Renderer>();
				foreach (Renderer val in array)
				{
					if (!((Object)(object)val == (Object)null))
					{
						string name = ((Object)((Component)val).gameObject).name.ToLower();
						if (source.Any((string k) => name.Contains(k)) && val.enabled)
						{
							val.enabled = false;
							_hiddenRenderers.Add(val);
							Log.LogDebug((object)("[SpectatorCamera] Hidden renderer (fallback): " + ((Object)((Component)val).gameObject).name + " (" + ((object)val).GetType().Name + ")"));
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[SpectatorCamera] Fallback arm hiding failed: " + ex.Message));
			}
		}

		private void ShowPlayerArmRenderers()
		{
			int count = _hiddenRenderers.Count;
			foreach (Renderer hiddenRenderer in _hiddenRenderers)
			{
				if ((Object)(object)hiddenRenderer != (Object)null)
				{
					try
					{
						hiddenRenderer.enabled = true;
					}
					catch
					{
					}
				}
			}
			_hiddenRenderers.Clear();
			Log.LogInfo((object)$"[SpectatorCamera] Restored {count} player arm/weapon renderers");
		}
	}
	public class SpectatorUI
	{
		private GUIStyle _labelStyle;

		private GUIStyle _titleStyle;

		private GUIStyle _hintStyle;

		private Texture2D _gradientTexture;

		private Texture2D _hpBarBgTexture;

		private Texture2D _hpBarFillTexture;

		private Texture2D _hpBarFillLowTexture;

		private Font _ultrakillFont;

		private Rect _barRect;

		private bool _stylesInitialized;

		private bool _showNoEnemiesMessage;

		private float _noEnemiesMessageTimer;

		private const float BarHeight = 60f;

		private const float BarPadding = 15f;

		private static ManualLogSource Log => EnemySpectatePlugin.Log;

		public void Initialize()
		{
			Log.LogInfo((object)"[SpectatorUI] Initialized (styles will be set up on first OnGUI)");
		}

		private void EnsureStylesInitialized()
		{
			//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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			//IL_0122: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: 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_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: 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_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			if (!_stylesInitialized)
			{
				_ultrakillFont = LoadUltrakillFont();
				if ((Object)(object)_ultrakillFont != (Object)null)
				{
					Log.LogInfo((object)"[SpectatorUI] Loaded ULTRAKILL font (VCR_OSD_MONO)");
				}
				else
				{
					Log.LogWarning((object)"[SpectatorUI] Could not load ULTRAKILL font, using default");
				}
				_gradientTexture = MakeGradientTexture(1, 4, Color.black, Color.red);
				_hpBarBgTexture = MakeTex(1, 1, new Color(0.2f, 0.2f, 0.2f, 0.9f));
				_hpBarFillTexture = MakeTex(1, 1, new Color(0.2f, 0.8f, 0.2f, 0.9f));
				_hpBarFillLowTexture = MakeTex(1, 1, new Color(0.9f, 0.2f, 0.2f, 0.9f));
				GUIStyle val = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16
				};
				val.normal.textColor = Color.white;
				val.alignment = (TextAnchor)3;
				val.wordWrap = false;
				val.font = _ultrakillFont;
				_labelStyle = val;
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 20
				};
				val2.normal.textColor = Color.white;
				val2.alignment = (TextAnchor)3;
				val2.wordWrap = false;
				val2.font = _ultrakillFont;
				_titleStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 12
				};
				val3.normal.textColor = new Color(1f, 0.5f, 0.5f);
				val3.alignment = (TextAnchor)3;
				val3.wordWrap = false;
				val3.font = _ultrakillFont;
				_hintStyle = val3;
				_stylesInitialized = true;
				Log.LogDebug((object)"[SpectatorUI] Styles initialized");
			}
		}

		private Font LoadUltrakillFont()
		{
			try
			{
				Font[] array = Resources.FindObjectsOfTypeAll<Font>();
				foreach (Font val in array)
				{
					if (((Object)val).name.ToLower().Contains("vcr") || ((Object)val).name.ToLower().Contains("osd") || ((Object)val).name.ToLower().Contains("mono"))
					{
						Log.LogDebug((object)("[SpectatorUI] Found font: " + ((Object)val).name));
						return val;
					}
				}
				string text = Path.Combine(Application.streamingAssetsPath, "cgef", "data", "flutter_assets", "assets", "fonts", "VCR_OSD_MONO.ttf");
				if (File.Exists(text))
				{
					Log.LogDebug((object)("[SpectatorUI] Found font file at: " + text));
				}
				string[] array2 = new string[3] { "Fonts/VCR_OSD_MONO", "VCR_OSD_MONO", "Fonts/vcr_osd_mono" };
				foreach (string text2 in array2)
				{
					Font val2 = Resources.Load<Font>(text2);
					if ((Object)(object)val2 != (Object)null)
					{
						Log.LogDebug((object)("[SpectatorUI] Loaded font from Resources: " + text2));
						return val2;
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[SpectatorUI] Font load error: " + ex.Message));
			}
			return null;
		}

		private void OnDestroy()
		{
			if ((Object)(object)_gradientTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_gradientTexture);
				_gradientTexture = null;
			}
		}

		public void OnEnemyChanged(EnemyIdentifier enemy)
		{
		}

		public void ShowNoEnemiesMessage()
		{
			_showNoEnemiesMessage = true;
			_noEnemiesMessageTimer = 3f;
		}

		public void OnGUI()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: 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_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Expected O, but got Unknown
			if (!EnemySpectatePlugin.Instance.IsSpectating)
			{
				return;
			}
			EnsureStylesInitialized();
			if (_showNoEnemiesMessage)
			{
				_noEnemiesMessageTimer -= Time.deltaTime;
				if (_noEnemiesMessageTimer <= 0f)
				{
					_showNoEnemiesMessage = false;
				}
			}
			float num = Screen.width;
			float num2 = 60f;
			_barRect = new Rect(0f, (float)Screen.height - num2, num, num2);
			GUI.DrawTexture(_barRect, (Texture)(object)_gradientTexture, (ScaleMode)0);
			GUI.Box(new Rect(0f, (float)Screen.height - num2 - 1f, num, 1f), "", GUI.skin.box);
			GUILayout.BeginArea(_barRect);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Space(15f);
			EnemyIdentifier val = EnemySpectatePlugin.Instance.EnemyTracker?.CurrentEnemy;
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Space(6f);
			string text = ((EnemySpectatePlugin.Instance.CameraMode == SpectatorCameraMode.Cinematic) ? "EVERY ENEMY" : (((Object)(object)val != (Object)null) ? EnemySpectatePlugin.Instance.EnemyTracker.GetEnemyDisplayName(val) : ((!_showNoEnemiesMessage) ? "None" : "NO ENEMIES FOUND")));
			GUILayout.Label("NOW SPECTATING: " + text, _titleStyle, Array.Empty<GUILayoutOption>());
			string text2 = "";
			if ((Object)(object)val != (Object)null)
			{
				int num3 = EnemySpectatePlugin.Instance.EnemyTracker.CurrentEnemyIndex + 1;
				int enemyCount = EnemySpectatePlugin.Instance.EnemyTracker.EnemyCount;
				text2 = string.Format(arg2: (EnemySpectatePlugin.Instance.CameraMode == SpectatorCameraMode.Orbit) ? "ORBIT" : ((EnemySpectatePlugin.Instance.CameraMode != SpectatorCameraMode.Follow) ? "CINEMATIC" : "FOLLOW"), format: "Enemy {0}/{1}  |  Mode: {2}  |  SPACE: Change  MMB: Rotate  Scroll: Zoom  F5: Exit", arg0: num3, arg1: enemyCount);
			}
			else if (EnemySpectatePlugin.Instance.CameraMode == SpectatorCameraMode.Cinematic)
			{
				int enemyCount2 = EnemySpectatePlugin.Instance.EnemyTracker.EnemyCount;
				text2 = $"CINEMATIC MODE  |  {enemyCount2} enemies  |  Scroll: Zoom  F5: Exit";
			}
			else
			{
				text2 = "No enemies available  |  F5: Exit Spectator";
			}
			GUILayout.Label(text2, _hintStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(6f);
			GUILayout.EndVertical();
			GUILayout.FlexibleSpace();
			if ((Object)(object)val != (Object)null)
			{
				DrawHPBar(val);
			}
			else
			{
				GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
				GUILayout.Space(6f);
				GUIStyle val2 = new GUIStyle(_hintStyle)
				{
					alignment = (TextAnchor)5
				};
				val2.normal.textColor = Color.red;
				GUILayout.Label("SPECTATOR ACTIVE", val2, Array.Empty<GUILayoutOption>());
				GUILayout.Space(6f);
				GUILayout.EndVertical();
			}
			GUILayout.Space(15f);
			GUILayout.EndHorizontal();
			GUILayout.EndArea();
		}

		private void DrawHPBar(EnemyIdentifier enemy)
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: 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_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Expected O, but got Unknown
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Expected O, but got Unknown
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Expected O, but got Unknown
			//IL_02a0: 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_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Expected O, but got Unknown
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Expected O, but got Unknown
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Expected O, but got Unknown
			try
			{
				float num = 0f;
				float num2 = 0f;
				FieldInfo field = typeof(EnemyIdentifier).GetField("health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					num = (float)(field.GetValue(enemy) ?? ((object)0f));
				}
				Enemy component = ((Component)enemy).GetComponent<Enemy>();
				if ((Object)(object)component != (Object)null)
				{
					FieldInfo field2 = typeof(Enemy).GetField("originalHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field2 != null)
					{
						num2 = (float)(field2.GetValue(component) ?? ((object)0f));
					}
				}
				if (num2 > 0f)
				{
					FieldInfo field3 = typeof(EnemyIdentifier).GetField("totalHealthModifier", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field3 != null)
					{
						float num3 = (float)(field3.GetValue(enemy) ?? ((object)1f));
						num2 *= num3;
					}
				}
				if (num2 <= 0f)
				{
					num2 = num;
				}
				float num4 = ((num2 > 0f) ? Mathf.Clamp01(num / num2) : 1f);
				Texture2D background = MakeTex(1, 1, Color.black);
				Texture2D background2 = ((num4 > 0.3f) ? _hpBarFillTexture : _hpBarFillLowTexture);
				GUIStyle val = new GUIStyle(_hintStyle)
				{
					fontSize = 16
				};
				val.normal.textColor = Color.white;
				val.alignment = (TextAnchor)4;
				val.font = _ultrakillFont;
				GUIStyle val2 = val;
				GUIStyle val3 = new GUIStyle(_hintStyle)
				{
					fontSize = 10
				};
				val3.normal.textColor = Color.white;
				val3.alignment = (TextAnchor)4;
				val3.font = _ultrakillFont;
				GUIStyle val4 = val3;
				GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) });
				GUILayout.Label("+", val2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) });
				GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(220f),
					GUILayout.Height(26f)
				});
				GUILayout.Space(3f);
				Rect rect = GUILayoutUtility.GetRect(0f, 0f, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.ExpandWidth(true),
					GUILayout.Height(20f)
				});
				Rect val5 = new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height);
				GUIStyle val6 = new GUIStyle();
				val6.normal.background = background;
				GUI.Box(val5, "", val6);
				Rect val7 = new Rect(((Rect)(ref rect)).x + 1f, ((Rect)(ref rect)).y + 1f, ((Rect)(ref rect)).width - 2f, ((Rect)(ref rect)).height - 2f);
				GUIStyle val8 = new GUIStyle();
				val8.normal.background = _hpBarBgTexture;
				GUI.Box(val7, "", val8);
				if (num4 > 0f)
				{
					float num5 = Mathf.Max(1f, (((Rect)(ref rect)).width - 4f) * num4);
					Rect val9 = new Rect(((Rect)(ref rect)).x + 2f, ((Rect)(ref rect)).y + 2f, num5, ((Rect)(ref rect)).height - 4f);
					GUIStyle val10 = new GUIStyle();
					val10.normal.background = background2;
					GUI.Box(val9, "", val10);
				}
				string text = $"{Mathf.CeilToInt(num)} / {Mathf.CeilToInt(num2)}";
				GUI.Label(val7, text, new GUIStyle(val4)
				{
					alignment = (TextAnchor)4,
					fontSize = 12
				});
				GUILayout.EndVertical();
				GUILayout.EndHorizontal();
			}
			catch (Exception ex)
			{
				Log.LogDebug((object)("[SpectatorUI] HP bar error: " + ex.Message));
			}
		}

		private Texture2D MakeTex(int width, int height, Color col)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			Color[] array = (Color[])(object)new Color[width * height];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = col;
			}
			Texture2D val = new Texture2D(width, height);
			val.SetPixels(array);
			val.Apply();
			return val;
		}

		private Texture2D MakeGradientTexture(int width, int height, Color topColor, Color bottomColor)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			Color[] array = (Color[])(object)new Color[width * height];
			for (int i = 0; i < height; i++)
			{
				float num = (float)i / (float)Mathf.Max(height - 1, 1);
				Color val = Color.Lerp(topColor, bottomColor, num);
				for (int j = 0; j < width; j++)
				{
					array[i * width + j] = val;
				}
			}
			Texture2D val2 = new Texture2D(width, height);
			val2.SetPixels(array);
			val2.Apply();
			return val2;
		}
	}
}