Decompiled source of Spectate v1.5.10

Spectate.dll

Decompiled 10 minutes ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using AIGraph;
using Agents;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using CellMenu;
using CullingSystem;
using Enemies;
using GameData;
using Globals;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using Spectate.Config;
using Spectate.Patches;
using Spectate.Patches.Compat;
using Spectate.UI;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Spectate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Spectate")]
[assembly: AssemblyTitle("Spectate")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
namespace Spectate
{
	public class AgentTarget
	{
		public readonly PlayerAgent Agent;

		public Transform Transform => ((Component)Agent).transform;

		public FPSCamera? FPSCamera => Agent.FPSCamera;

		public FirstPersonItemHolder? FPHolder => Agent.FPItemHolder;

		public PlayerLocomotion Locomotion => Agent.Locomotion;

		public PLOC_State LocomotionStateEnum => Locomotion.m_currentStateEnum;

		public bool IsDowned => (int)LocomotionStateEnum == 7;

		public PlayerSyncModelData PlayerModel => Agent.PlayerSyncModel;

		public SNet_Player SAgent => Agent.Owner;

		public bool IsBot => SAgent.IsBot;

		public bool IsLocal => SAgent.IsLocal;

		public Dam_PlayerDamageBase Damage => Agent.Damage;

		public float Health => ((Dam_SyncedDamageBase)Damage).Health / ((Dam_SyncedDamageBase)Damage).HealthMax;

		public float HealthPercent => Health * 100f;

		public float Infection => Damage.Infection;

		public float InfectionPercent => Infection * 100f;

		public PlayerInventoryBase? Inventory => Agent.Inventory;

		public InventorySlot? ActiveItemSlot
		{
			get
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				PlayerInventoryBase? inventory = Inventory;
				if (inventory == null)
				{
					return null;
				}
				return inventory.WieldedSlot;
			}
		}

		public AIG_CourseNode? CourseNode
		{
			get
			{
				if (IsCaptured)
				{
					PouncerTracker? instance = PouncerTracker.Instance;
					if (instance != null && instance.TryGetCapturingPouncer(Agent, out PouncerBehaviour capturingPouncer))
					{
						object obj;
						if (capturingPouncer == null)
						{
							obj = null;
						}
						else
						{
							EnemyAI ai = ((EnemyBehaviour)capturingPouncer).m_ai;
							if (ai == null)
							{
								obj = null;
							}
							else
							{
								EnemyAgent enemyAgent = ai.m_enemyAgent;
								obj = ((enemyAgent != null) ? ((Agent)enemyAgent).CourseNode : null);
							}
						}
						if (obj == null)
						{
							obj = ((Agent)Agent).CourseNode;
						}
						return (AIG_CourseNode?)obj;
					}
				}
				return ((Agent)Agent).CourseNode;
			}
		}

		public PlayerBackpack? Backpack => PlayerBackpackManager.GetBackpack(Agent.Owner);

		public PlayerAmmoStorage? AmmoStorage
		{
			get
			{
				PlayerBackpack? backpack = Backpack;
				if (backpack == null)
				{
					return null;
				}
				return backpack.AmmoStorage;
			}
		}

		public bool HasClipData
		{
			get
			{
				if (IsLocal)
				{
					return true;
				}
				if (PlayerManager.GetLocalPlayerAgent().Owner.IsMaster && IsBot)
				{
					return true;
				}
				return false;
			}
		}

		public bool IsCaptured
		{
			get
			{
				if ((Object)(object)PouncerTracker.Instance != (Object)null)
				{
					return PouncerTracker.Instance.IsCaptured(Agent);
				}
				return false;
			}
		}

		public static bool CanSpectate(PlayerAgent agent)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			bool num = (int)agent.Locomotion.m_currentStateEnum == 7;
			bool flag = (Object)(object)PouncerTracker.Instance != (Object)null && PouncerTracker.Instance.IsCaptured(agent);
			if (num)
			{
				return !flag;
			}
			return false;
		}

		public AgentTarget(PlayerAgent agent)
		{
			Agent = agent;
		}

		public void SetRigActive(bool active)
		{
			Util.SetTargetActiveIfDiff(((Component)Agent.PlayerSyncModel).gameObject, active);
		}

		public void SetHostHiddenRigActive(bool active)
		{
			PlayerSyncModelData playerSyncModel = Agent.PlayerSyncModel;
			if (((Il2CppArrayBase<GameObject>)(object)playerSyncModel.m_gfxHead).Count == 0 || ((Il2CppArrayBase<GameObject>)(object)playerSyncModel.m_gfxArms).Count == 0)
			{
				Util.FindAndSortGfxParts(((Component)playerSyncModel).gameObject, out GameObject[] gfxHead, out GameObject[] gfxArms, out GameObject[] gfxTorso, out GameObject[] gfxLegs);
				playerSyncModel.m_gfxHead = Il2CppReferenceArray<GameObject>.op_Implicit(gfxHead);
				playerSyncModel.m_gfxArms = Il2CppReferenceArray<GameObject>.op_Implicit(gfxArms);
				playerSyncModel.m_gfxTorso = Il2CppReferenceArray<GameObject>.op_Implicit(gfxTorso);
				playerSyncModel.m_gfxLegs = Il2CppReferenceArray<GameObject>.op_Implicit(gfxLegs);
			}
			playerSyncModel.SetHeadVisible(active, active);
			playerSyncModel.SetArmsVisible(active, active);
		}

		public void SetRigTorsoLegsActive(bool active)
		{
			PlayerSyncModelData playerSyncModel = Agent.PlayerSyncModel;
			playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxLegs, active, active);
			playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxTorso, active, active);
		}

		public static bool operator ==(AgentTarget? a, AgentTarget? b)
		{
			if ((object)a == b)
			{
				return true;
			}
			if ((object)a == null)
			{
				if ((object)b != null)
				{
					return (Object)(object)b.Agent == (Object)null;
				}
				return true;
			}
			if ((object)b == null)
			{
				return (Object)(object)a.Agent == (Object)null;
			}
			return (Object)(object)a.Agent == (Object)(object)b.Agent;
		}

		public static bool operator !=(AgentTarget? a, AgentTarget? b)
		{
			return !(a == b);
		}

		public override bool Equals(object? other)
		{
			if (other is AgentTarget agentTarget)
			{
				return this == agentTarget;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return ((Object)Agent).GetHashCode();
		}
	}
	public static class Events
	{
		public static event Action? OnSessionEnd;

		public static event Action? OnSessionStart;

		public static event Action? OnAnyPlayerDeath;

		public static event Action? OnCheckpointReload;

		internal static void RaiseSessionEnd()
		{
			Events.OnSessionEnd?.Invoke();
		}

		internal static void RaiseSessionStart()
		{
			Events.OnSessionStart?.Invoke();
		}

		internal static void RaiseAnyPlayerDeath()
		{
			Events.OnAnyPlayerDeath?.Invoke();
		}

		internal static void RaiseCheckpointReload()
		{
			Events.OnCheckpointReload?.Invoke();
		}
	}
	public class InputHelper
	{
		public static int GetAlphaNumKeyDown()
		{
			int result = -1;
			for (int i = 0; i < 10; i++)
			{
				if (Input.GetKeyDown((KeyCode)(48 + i)))
				{
					result = i;
					break;
				}
			}
			return result;
		}

		public static bool OnlyModifies(KeyCode mod, KeyCode altMod = 0, KeyCode nonMod = 0)
		{
			//IL_0000: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Invalid comparison between Unknown and I4
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Invalid comparison between Unknown and I4
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Invalid comparison between Unknown and I4
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Invalid comparison between Unknown and I4
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Invalid comparison between Unknown and I4
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			bool num = Input.GetKey(mod) || Input.GetKey(altMod) || Input.GetKeyDown(nonMod);
			bool flag = false;
			if ((int)mod != 304 && (int)mod != 303 && (int)altMod != 304 && (int)altMod != 303)
			{
				flag |= Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
			}
			if ((int)mod != 306 && (int)mod != 305 && (int)altMod != 306 && (int)altMod != 305)
			{
				flag |= Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305);
			}
			if ((int)mod != 308 && (int)mod != 307 && (int)altMod != 308 && (int)altMod != 307)
			{
				flag |= Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307);
			}
			if (num)
			{
				return !flag;
			}
			return false;
		}

		public static Vector2 GetMouseDelta()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2(InputMapper.GetAxis.Invoke((InputAction)3, (eFocusState)0), InputMapper.GetAxis.Invoke((InputAction)4, (eFocusState)0));
		}
	}
	internal static class Logger
	{
		private static ManualLogSource _mLogSource;

		public static bool Ready => _mLogSource != null;

		public static void Setup()
		{
			_mLogSource = Logger.CreateLogSource("io.takina.gtfo.Spectate");
		}

		public static void SetupFromInit(ManualLogSource logSource)
		{
			_mLogSource = logSource;
		}

		private static string Format(object data)
		{
			return data.ToString();
		}

		public static void Debug(object msg)
		{
			if (ConfigMgr.Debug)
			{
				_mLogSource.LogInfo((object)("[DEBUG] " + Format(msg)));
			}
			else
			{
				_mLogSource.LogDebug((object)Format(msg));
			}
		}

		public static void Info(object msg)
		{
			_mLogSource.LogInfo((object)Format(msg));
		}

		public static void Warn(object msg)
		{
			_mLogSource.LogWarning((object)Format(msg));
		}

		public static void Error(object msg)
		{
			_mLogSource.LogError((object)Format(msg));
		}

		public static void Fatal(object msg)
		{
			_mLogSource.LogFatal((object)Format(msg));
		}
	}
	[BepInPlugin("io.takina.gtfo.Spectate", "Spectate", "1.5.10")]
	public class Plugin : BasePlugin
	{
		public const string NAME = "Spectate";

		public const string GUID = "io.takina.gtfo.Spectate";

		public const string VERSION = "1.5.10";

		public static GameObject? PluginObject;

		public event Action? OnManagersSetup;

		public override void Load()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_008b: Expected O, but got Unknown
			Logger.Setup();
			Logger.Info("Spectate [io.takina.gtfo.Spectate @ 1.5.10]");
			Harmony val = new Harmony("io.takina.gtfo.Spectate");
			ConfigMgr.Process();
			ClassInjector.RegisterTypeInIl2Cpp<SpectateCam>();
			ClassInjector.RegisterTypeInIl2Cpp<SpectateUI>();
			ClassInjector.RegisterTypeInIl2Cpp<SpectateConfigUpdater>();
			ClassInjector.RegisterTypeInIl2Cpp<PouncerTracker>();
			ClassInjector.RegisterTypeInIl2Cpp<PouncerTrackingDart>();
			ClassInjector.RegisterTypeInIl2Cpp<Wm>();
			OnManagersSetup += Initialize;
			Global.OnAllManagersSetup += Action.op_Implicit(this.OnManagersSetup);
			Logger.Info("Patching...");
			ApplyPatch<EventPatch>(val);
			ApplyPatch<UIPatch>(val);
			ApplyPatch<CameraPatch>(val);
			ApplyPatch<AnimationPatch>(val);
			ApplyPatch<PouncerPatch>(val);
			CompatPatcher.PatchAll(val);
			Logger.Info("Finished Patching");
		}

		private static void ApplyPatch<T>(Harmony h)
		{
			h.PatchAll(typeof(T));
		}

		private void Initialize()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			Logger.Debug("Initializing Spectate GameObject's...");
			PluginObject = new GameObject("io.takina.gtfo.Spectate");
			Object.DontDestroyOnLoad((Object)(object)PluginObject);
			SpectateUI spectateUI = PluginObject.AddComponent<SpectateUI>();
			PluginObject.AddComponent<SpectateCam>();
			PluginObject.AddComponent<SpectateConfigUpdater>();
			PluginObject.AddComponent<PouncerTracker>();
			PluginObject.AddComponent<Wm>();
			spectateUI.ReplicateUI();
		}

		public override bool Unload()
		{
			ConfigMgr.WriteConfigIfDirty();
			return true;
		}
	}
	public class PouncerTracker : MonoBehaviour
	{
		private const float CleanupDelay = 10f;

		private float _timeUntilCleanup;

		public static PouncerTracker? Instance { get; private set; }

		public bool IsLocalPlayerSnatched { get; private set; }

		private List<PouncerBehaviour> ActivePouncers { get; } = new List<PouncerBehaviour>();


		public PouncerTracker(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			else if ((Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)this);
			}
		}

		private void Update()
		{
			if (_timeUntilCleanup > 0f)
			{
				_timeUntilCleanup -= Time.deltaTime;
				if (_timeUntilCleanup <= 0f)
				{
					CleanupPouncers();
					_timeUntilCleanup = 10f;
				}
			}
		}

		public void RegisterPouncer(PouncerBehaviour pouncer)
		{
			if (!ActivePouncers.Contains(pouncer))
			{
				ActivePouncers.Add(pouncer);
				((Component)pouncer).gameObject.AddComponent<PouncerTrackingDart>();
				IsLocalPlayerSnatched = true;
			}
		}

		public void UnregisterPouncer(GameObject pouncer)
		{
			foreach (PouncerBehaviour activePouncer in ActivePouncers)
			{
				if ((Object)(object)((Component)activePouncer).gameObject == (Object)(object)pouncer || ((Il2CppObjectBase)((Component)activePouncer).gameObject).Pointer == ((Il2CppObjectBase)pouncer).Pointer)
				{
					ActivePouncers.Remove(activePouncer);
					break;
				}
			}
		}

		public bool IsCaptured(PlayerAgent agent)
		{
			foreach (PouncerBehaviour activePouncer in ActivePouncers)
			{
				if (!((Object)(object)activePouncer == (Object)null) && !((Object)(object)activePouncer.CapturedPlayer == (Object)null) && ((Il2CppObjectBase)activePouncer.CapturedPlayer).Pointer == ((Il2CppObjectBase)agent).Pointer)
				{
					return true;
				}
			}
			return false;
		}

		public bool TryGetCapturingPouncer(PlayerAgent agent, out PouncerBehaviour? capturingPouncer)
		{
			foreach (PouncerBehaviour activePouncer in ActivePouncers)
			{
				if (!((Object)(object)activePouncer == (Object)null) && !((Object)(object)activePouncer.CapturedPlayer == (Object)null) && ((Il2CppObjectBase)activePouncer.CapturedPlayer).Pointer == ((Il2CppObjectBase)agent).Pointer)
				{
					capturingPouncer = activePouncer;
					return true;
				}
			}
			capturingPouncer = null;
			return false;
		}

		private void CleanupPouncers()
		{
			ActivePouncers.RemoveAll((PouncerBehaviour p) => (Object)(object)p == (Object)null || !((Component)p).gameObject.activeInHierarchy);
		}
	}
	public class PouncerTrackingDart : MonoBehaviour
	{
		public PouncerTrackingDart(IntPtr ptr)
			: base(ptr)
		{
		}

		private void OnDestroy()
		{
			if ((Object)(object)PouncerTracker.Instance != (Object)null)
			{
				PouncerTracker.Instance.UnregisterPouncer(((Component)this).gameObject);
			}
		}
	}
	public class SpectateCam : MonoBehaviour
	{
		private bool _wasActive;

		private int _lastTargetPlayerIdx = -1;

		private bool _freecam = ConfigMgr.DefaultFreecamView;

		private bool _freecamFollow = ConfigMgr.AutoTransitionToFollowView;

		private float _freeLookReturnTimer;

		private PouncerBehaviour? _lastPouncer;

		public const float DownToSpectateDelay = 1f;

		private float _pitch = ConfigMgr.CameraPitchAngleDeg;

		private float _yaw;

		private float _pitchTarget = ConfigMgr.CameraPitchAngleDeg;

		private float _yawTarget;

		private float _eyeY;

		private float _eyeYTarget;

		private Vector3 _eyeXZ = Vector3.zero;

		private Vector3 _eyeXZTarget = Vector3.zero;

		private Vector3 _camPosComputed = Vector3.zero;

		public const float DefaultCameraYPositionLerpGain = 11f;

		public const float DefaultCameraXZPositionLerpGain = 15f;

		public const float DefaultCameraLerpGain = 6f;

		public const float DefaultOrbitCenterVerticalOffset = 0.325f;

		public const float DefaultPitchAngleDeg = -18.75f;

		public const float DefaultDistanceFromEye = 0.625f;

		public const float DefaultScrollSensitivity = 0.5f;

		public const float DefaultFreecamSensitivity = 1f;

		public const float OrbitCenterVerticalOffsetMin = -1f;

		public const float OrbitCenterVerticalOffsetMax = 5f;

		public const float DistanceMin = 0.1f;

		public const float DistanceMax = 5f;

		public const float DistanceOffsetPouncer = 1.3f;

		public const float PitchAngleDegMin = -89f;

		public const float PitchAngleDegMax = 89f;

		private AgentTarget? _self;

		private AgentTarget? _target;

		public static SpectateCam? Instance { get; set; }

		public bool SelfReady
		{
			get
			{
				if (_self != null)
				{
					return (Object)(object)_self.FPSCamera != (Object)null;
				}
				return false;
			}
		}

		public bool TargetReady => _target != null;

		public bool Active { get; private set; }

		public bool Freecam => _freecam;

		public C_Node? LastLocalCullNode { get; private set; }

		public Vector3 DiegeticCamDir { get; private set; } = Vector3.forward;


		public Vector3 DiegeticPlayerRigScale { get; private set; } = Vector3.one;


		public Vector3 CameraPos
		{
			get
			{
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: 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)
				if (!Active)
				{
					AgentTarget? self = _self;
					Vector3? obj;
					if ((object)self == null)
					{
						obj = null;
					}
					else
					{
						FPSCamera? fPSCamera = self.FPSCamera;
						obj = ((fPSCamera != null) ? new Vector3?(fPSCamera.Position) : null);
					}
					return (Vector3)(((??)obj) ?? Vector3.zero);
				}
				return _camPosComputed;
			}
		}

		public AgentTarget? Self
		{
			get
			{
				if (_self == null)
				{
					_self = new AgentTarget(PlayerManager.GetLocalPlayerAgent());
				}
				return _self;
			}
		}

		public AgentTarget? Target => _target;

		public bool CanSpectate
		{
			get
			{
				PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
				bool flag = (Object)(object)localPlayerAgent != (Object)null && AgentTarget.CanSpectate(localPlayerAgent);
				return ConfigMgr.DevEnables(eDevOpts.AllowSpectatingAnytime) || flag;
			}
		}

		public event Action? OnActive;

		public SpectateCam(IntPtr ptr)
			: base(ptr)
		{
		}//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_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)


		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)this);
			Events.OnSessionStart += delegate
			{
				Load();
			};
			Events.OnSessionEnd += delegate
			{
				Unload();
			};
			Events.OnAnyPlayerDeath += delegate
			{
				if (ConfigMgr.PreferSpectateAlive && (_target == null || _target.IsDowned))
				{
					TrySetAnyNonLocalTarget();
				}
			};
			Events.OnCheckpointReload += delegate
			{
				if (Active)
				{
					Detach();
				}
				Unload();
			};
		}

		public bool Load()
		{
			PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
			if ((Object)(object)localPlayerAgent == (Object)null)
			{
				Logger.Error("SpectateCam: Failed to load - local player agent is null");
				return false;
			}
			_self = new AgentTarget(localPlayerAgent);
			return (Object)(object)_self.FPSCamera != (Object)null;
		}

		public bool Unload()
		{
			SetActive(active: false);
			_self = null;
			_target = null;
			return true;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void SetTarget(PlayerAgent agent)
		{
			_target = new AgentTarget(agent);
		}

		public void TryAttachDelayed(float delay)
		{
			((MonoBehaviour)this).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(TryAttachDelayedCoroutine(delay)));
		}

		private IEnumerator TryAttachDelayedCoroutine(float delay)
		{
			yield return (object)new WaitForSeconds(delay);
			if (!Attach())
			{
				Logger.Warn("SpectateCam: TryAttachDelayed failed to attach after delay");
			}
		}

		public bool Attach()
		{
			//IL_0058: 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_00bb: 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)
			if (Active)
			{
				return true;
			}
			if (!SelfReady && !Load())
			{
				Logger.Error("SpectateCam: Attach failed - self not ready and cannot be loaded");
				return false;
			}
			if (!CanSpectate)
			{
				return false;
			}
			if (!TargetReady && !TrySetAnyNonLocalTarget())
			{
				Logger.Warn("SpectateCam: Attach failed - no valid target available");
				return false;
			}
			DiegeticCamDir = _self.FPSCamera.Forward;
			DiegeticPlayerRigScale = ((Component)_self.PlayerModel).gameObject.transform.localScale;
			AgentTarget? self = _self;
			object lastLocalCullNode;
			if ((object)self == null)
			{
				lastLocalCullNode = null;
			}
			else
			{
				AIG_CourseNode? courseNode = self.CourseNode;
				lastLocalCullNode = ((courseNode != null) ? courseNode.m_cullNode : null);
			}
			LastLocalCullNode = (C_Node?)lastLocalCullNode;
			((Component)_self.PlayerModel).gameObject.transform.localScale = Vector3.one;
			GuiManager.PlayerLayer.ApplyMovementSway(Vector3.zero);
			GuiManager.CrosshairLayer.ShowPrecisionDot();
			SpectateUI.Instance?.UpdateForAttach();
			SetRelatedActive(spectateActive: true);
			UpdateCull();
			SetActive(active: true);
			return true;
		}

		public bool Detach()
		{
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			if (!Active)
			{
				return true;
			}
			if (!SelfReady && !Load())
			{
				Logger.Error("SpectateCam: Detach failed - self not ready and cannot be loaded");
				Logger.Info("SpectateCam: Detach falling back to Unload");
				Unload();
				return false;
			}
			SetActive(active: false);
			SetRelatedActive(spectateActive: false);
			RevertCull();
			SpectateUI.Instance?.UpdateForDetach();
			CrosshairGuiLayer crosshairLayer = GuiManager.CrosshairLayer;
			if (crosshairLayer != null)
			{
				FirstPersonItemHolder? fPHolder = _self.FPHolder;
				float? obj;
				if (fPHolder == null)
				{
					obj = null;
				}
				else
				{
					ItemEquippable wieldedItem = fPHolder.WieldedItem;
					obj = ((wieldedItem != null) ? new float?(wieldedItem.HipFireCrosshairSize) : null);
				}
				crosshairLayer.ShowSpreadCircle(obj ?? 40f);
			}
			PlayerGuiLayer playerLayer = GuiManager.PlayerLayer;
			if (playerLayer != null)
			{
				PUI_LocalPlayerStatus playerStatus = playerLayer.m_playerStatus;
				if (playerStatus != null)
				{
					playerStatus.ResetDamageAnimation();
				}
			}
			((Component)_self.PlayerModel).gameObject.transform.localScale = DiegeticPlayerRigScale;
			return true;
		}

		private void SetActive(bool active)
		{
			if (active && !_wasActive)
			{
				this.OnActive?.Invoke();
			}
			_wasActive = Active;
			Active = active;
			if (!Active)
			{
				_yaw = 0f;
				_pitch = ConfigMgr.CameraPitchAngleDeg;
				_freeLookReturnTimer = 0f;
			}
		}

		internal void SetRelatedActive(bool spectateActive)
		{
			if (!SelfReady)
			{
				Logger.Error("SpectateCam: SetRelatedActive failed - self not ready");
				return;
			}
			if (ConfigMgr.ShowPlayerBodyWhenSpectating)
			{
				_self.SetHostHiddenRigActive(spectateActive);
				if (!Self.IsDowned && !spectateActive)
				{
					_self.SetRigTorsoLegsActive(active: true);
				}
				else
				{
					_self.SetRigTorsoLegsActive(spectateActive);
				}
			}
			else
			{
				_self.SetRigActive(!spectateActive);
			}
			_self.Agent.DeadDebugMode = spectateActive;
			_self.PlayerModel.GhostEnabled = spectateActive;
			Util.SetTargetActiveIfDiff((Behaviour?)(object)_self.Inventory, !spectateActive);
			PlayerInventoryBase? inventory = _self.Inventory;
			Util.SetTargetActiveIfDiff((inventory != null) ? ((Component)inventory.m_flashlight).gameObject : null, !spectateActive);
			FirstPersonItemHolder? fPHolder = _self.FPHolder;
			Util.SetTargetActiveIfDiff((fPHolder != null) ? ((Component)fPHolder).gameObject : null, !spectateActive);
			FirstPersonItemHolder? fPHolder2 = _self.FPHolder;
			if (fPHolder2 != null)
			{
				PlayerFPSBody fPSArms = fPHolder2.FPSArms;
				if (fPSArms != null)
				{
					fPSArms.SetVisible(!spectateActive && !_self.IsDowned);
				}
			}
			FPSCamera fPSCamera = _self.FPSCamera;
			if ((Object)(object)fPSCamera != (Object)null)
			{
				fPSCamera.MouseLookEnabled = !spectateActive;
				fPSCamera.PlayerAgentRotationEnabled = !spectateActive;
			}
		}

		private void Update()
		{
			if (!((Behaviour)this).enabled || !((Component)this).gameObject.activeInHierarchy)
			{
				return;
			}
			ProcessInput();
			UpdateTransitions();
			if (Active)
			{
				if (!TargetReady || !SelfReady)
				{
					Detach();
					return;
				}
				UpdateLerp(_freecam);
				UpdateCamera();
				UpdateCull();
			}
		}

		private void UpdateTransitions()
		{
			if (SelfReady)
			{
				if (Active && !_self.IsDowned && !ConfigMgr.DevEnables(eDevOpts.AllowSpectatingAnytime))
				{
					Detach();
				}
				else if (Active && ConfigMgr.AutoTransitionToFollowView && _freeLookReturnTimer >= 0f)
				{
					_freeLookReturnTimer -= Time.deltaTime;
				}
			}
		}

		private void ProcessInput()
		{
			//IL_0017: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Invalid comparison between Unknown and I4
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			if (!InputMapper.Current.FocusStateFilterPass((eFocusState)4))
			{
				return;
			}
			if (CanSpectate && Input.GetKeyDown(ConfigMgr.GetKeybind(SpectateInputAction.ToggleSpectate)))
			{
				if (Active)
				{
					if (!Detach())
					{
						Logger.Warn("SpectateCam: Failed to detach SpecCam");
					}
				}
				else if (!Attach())
				{
					Logger.Warn("SpectateCam: Failed to attach SpecCam");
				}
			}
			if (!Active)
			{
				return;
			}
			if (Input.GetKeyDown(ConfigMgr.GetKeybind(SpectateInputAction.ToggleFreecam)))
			{
				if (_freecam)
				{
					_freecam = false;
					OnFree2Follow();
				}
				else
				{
					_freecam = true;
					OnFollow2Free();
				}
			}
			if (_freecam && Input.GetKeyDown(ConfigMgr.GetKeybind(SpectateInputAction.ToggleAutoFollow)))
			{
				ConfigMgr.AutoTransitionToFollowView = !ConfigMgr.AutoTransitionToFollowView;
				SpectateUI.Instance?.MarkUIDirty();
			}
			Vector2 mouseDelta = InputHelper.GetMouseDelta();
			if (_freecam && mouseDelta != Vector2.zero)
			{
				AdjustYaw(mouseDelta.x * ConfigMgr.FreecamSensitivity);
				AdjustPitch(mouseDelta.y * ConfigMgr.FreecamSensitivity);
				if (ConfigMgr.AutoTransitionToFollowView)
				{
					_freecamFollow = false;
					_freeLookReturnTimer = ConfigMgr.AutoTransitionDelay;
				}
			}
			if (_freecam)
			{
				if (Input.GetKey((KeyCode)273))
				{
					AdjustPitch(ConfigMgr.FreecamSensitivity);
				}
				if (Input.GetKey((KeyCode)274))
				{
					AdjustPitch(0f - ConfigMgr.FreecamSensitivity);
				}
				if (Input.GetKey((KeyCode)276))
				{
					AdjustYaw(0f - ConfigMgr.FreecamSensitivity);
				}
				if (Input.GetKey((KeyCode)275))
				{
					AdjustYaw(ConfigMgr.FreecamSensitivity);
				}
			}
			if (Input.GetKeyDown((KeyCode)323))
			{
				TrySetNextTarget();
			}
			if (Input.GetKeyDown((KeyCode)324))
			{
				TrySetPreviousTarget();
			}
			if ((int)FocusStateManager.Current.m_currentState != 6)
			{
				int alphaNumKeyDown = InputHelper.GetAlphaNumKeyDown();
				if (alphaNumKeyDown > 0)
				{
					TrySetTargetByIdx(alphaNumKeyDown - 1, overridePreferAlive: true);
				}
			}
			float num = Input.mouseScrollDelta.y * ConfigMgr.ScrollSensitivity;
			if (InputMapper.Current.FocusStateFilterPass((eFocusState)6) || !(Mathf.Abs(num) > 0f))
			{
				return;
			}
			if (InputHelper.OnlyModifies((KeyCode)304, (KeyCode)303, (KeyCode)0))
			{
				if (_freecam)
				{
					SpectateUI.Instance?.WarnFreecamNoAdjustPitch();
				}
				else
				{
					ConfigMgr.CameraPitchAngleDeg -= 0.5f * num;
				}
			}
			else if (InputHelper.OnlyModifies((KeyCode)306, (KeyCode)305, (KeyCode)0))
			{
				ConfigMgr.CameraOrbitVerticalOffset = Mathf.Clamp(ConfigMgr.CameraOrbitVerticalOffset + 0.05f * num, -1f, 5f);
			}
			else
			{
				ConfigMgr.CameraDistance = Mathf.Clamp(ConfigMgr.CameraDistance - 0.05f * num, 0.1f, 5f);
			}
		}

		private void UpdateCamera()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: 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_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_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_0134: 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_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: 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_014b: 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_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: 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)
			if (!SelfReady || !TargetReady)
			{
				Logger.Error("SpectateCam: UpdateCamera failed - target or self not ready");
				return;
			}
			if (ConfigMgr.AutoTransitionToFollowView && _freecam)
			{
				if (_freeLookReturnTimer < 0.001f)
				{
					_freecamFollow = true;
				}
				if (_freecamFollow)
				{
					UpdateYawPitchWithFollowView(instant: false);
				}
			}
			SetEye(GetTargetOrbitCenter());
			Vector3 val = _eyeXZ + Vector3.up * _eyeY;
			Vector3 forward = ((Agent)_target.Agent).Forward;
			Vector3 val2 = ((Vector3)(ref forward)).normalized;
			if (_freecam)
			{
				val2 = Quaternion.Euler(0f, _yaw, 0f) * Vector3.forward;
			}
			float num = (float)Math.PI / 180f * (_freecam ? _pitch : ConfigMgr.CameraPitchAngleDeg);
			Vector3 val3 = val2 + Vector3.up * Mathf.Tan(num);
			((Vector3)(ref val3)).Normalize();
			float num2 = ConfigMgr.CameraDistance;
			if (_target.IsCaptured)
			{
				num2 = Mathf.Clamp(num2 + 1.3f, 0.1f, 5f);
			}
			_camPosComputed = val - val3 * num2;
			RaycastHit val4 = default(RaycastHit);
			if (Physics.Raycast(val, -val3, ref val4, num2, LayerManager.MASK_WORLD))
			{
				_camPosComputed = val4.m_Point + val3 * 0.1f;
			}
			_self.FPSCamera.OverridePositionAndRotation(_camPosComputed, Quaternion.LookRotation(val3));
			_self.FPSCamera.OverrideFieldOfView((float)CellSettingsManager.GetIntValue((eCellSettingID)52));
		}

		private void UpdateLerp(bool freecamEnabled)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			_eyeXZ = Vector3.Lerp(_eyeXZ, _eyeXZTarget, Time.deltaTime * ConfigMgr.CameraXZLerpGain);
			_eyeY = Mathf.Lerp(_eyeY, _eyeYTarget, Time.deltaTime * ConfigMgr.CameraYLerpGain);
			if (freecamEnabled)
			{
				_yaw = Mathf.LerpAngle(_yaw, _yawTarget, Time.deltaTime * ConfigMgr.FreecamLerpGain);
				float num = _yawTarget - _yaw;
				_yaw = Mathf.Repeat(_yaw, 360f);
				_yawTarget = _yaw + num;
				_pitch = Mathf.LerpAngle(_pitch, _pitchTarget, Time.deltaTime * ConfigMgr.FreecamLerpGain);
			}
		}

		private void UpdateCull()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0053: 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_003b: 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)
			if (!SelfReady || !TargetReady)
			{
				Logger.Error("SpectateCam: UpdateCull failed - target or self not ready");
				return;
			}
			Vector3 val = GetTargetOrbitCenter();
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(val, Vector3.down, ref val2, 64f, LayerManager.MASK_WORLD))
			{
				val = val2.m_Point;
			}
			CameraManager.CullingPosition = val;
			CameraManager.CullingDirection = _self.FPSCamera.Forward;
			_self.Agent.m_movingCuller.UpdatePosition(((Agent)_self.Agent).m_dimensionIndex, val);
			C_Node currentNode = _self.Agent.m_movingCuller.CurrentNode;
			AIG_CourseNode? courseNode = _target.CourseNode;
			C_Node val3 = ((courseNode != null) ? courseNode.m_cullNode : null);
			if (val3 != null)
			{
				if (((Il2CppObjectBase)currentNode).Pointer != ((Il2CppObjectBase)val3).Pointer)
				{
					_self.Agent.m_movingCuller.SetCurrentNode(val3);
				}
			}
			else
			{
				Logger.Warn("SpectateCam: UpdateCull - failed to sync cull nodes, target node is null");
			}
		}

		private void RevertCull()
		{
			//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_0024: 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_0044: 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_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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (!SelfReady)
			{
				Logger.Error("SpectateCam: RevertCull failed - self is not ready");
				return;
			}
			Vector3 val = ((Agent)_self.Agent).Position;
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(val, Vector3.down, ref val2, 64f, LayerManager.MASK_WORLD))
			{
				val = val2.m_Point;
			}
			CameraManager.CullingPosition = val;
			CameraManager.CullingDirection = _self.FPSCamera.Forward;
			_self.Agent.m_movingCuller.UpdatePosition(((Agent)_self.Agent).m_dimensionIndex, val);
			C_Node currentNode = _self.Agent.m_movingCuller.CurrentNode;
			if (LastLocalCullNode != null)
			{
				IntPtr? intPtr = ((currentNode != null) ? new IntPtr?(((Il2CppObjectBase)currentNode).Pointer) : null);
				C_Node? lastLocalCullNode = LastLocalCullNode;
				if (intPtr != ((lastLocalCullNode != null) ? new IntPtr?(((Il2CppObjectBase)lastLocalCullNode).Pointer) : null))
				{
					_self.Agent.m_movingCuller.SetCurrentNode(LastLocalCullNode);
				}
			}
			else
			{
				Logger.Warn("SpectateCam: RevertCull - failed to sync cull nodes self or target node is null");
			}
		}

		public void ClearTarget()
		{
			_target = null;
			_lastTargetPlayerIdx = -1;
		}

		private bool TrySetAnyNonLocalTarget()
		{
			//IL_003d: 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)
			SNet_PlayerSlotManager slots = SNet.Slots;
			List<SNet_Player> val = ((slots != null) ? slots.SlottedPlayers : null);
			if (val == null || val.Count == 0)
			{
				return false;
			}
			float num = float.MaxValue;
			_lastTargetPlayerIdx = -1;
			for (int i = 0; i < val.Count; i++)
			{
				if (SimulateSetTargetIdx(i, out PlayerAgent agent))
				{
					float num2 = Vector3.Distance(((Agent)agent).Position, ((Agent)_self.Agent).Position);
					if (num2 < num)
					{
						num = num2;
						_lastTargetPlayerIdx = i;
					}
				}
			}
			if (_lastTargetPlayerIdx != -1)
			{
				return TrySetTargetByIdx(_lastTargetPlayerIdx);
			}
			return false;
		}

		private bool TrySetNextTarget()
		{
			SNet_PlayerSlotManager slots = SNet.Slots;
			int num = ((slots == null) ? null : slots.SlottedPlayers?.Count) ?? (-1);
			if (num <= 0)
			{
				return false;
			}
			for (int i = 1; i <= num; i++)
			{
				int playerIdx = (_lastTargetPlayerIdx + i) % num;
				if (TrySetTargetByIdx(playerIdx))
				{
					return true;
				}
			}
			return false;
		}

		private bool TrySetPreviousTarget()
		{
			SNet_PlayerSlotManager slots = SNet.Slots;
			int num = ((slots == null) ? null : slots.SlottedPlayers?.Count) ?? (-1);
			if (num <= 0)
			{
				return false;
			}
			for (int i = 1; i <= num; i++)
			{
				int playerIdx = (_lastTargetPlayerIdx - i + num) % num;
				if (TrySetTargetByIdx(playerIdx))
				{
					return true;
				}
			}
			return false;
		}

		private bool SimulateSetTargetIdx(int playerIdx, [NotNullWhen(true)] out PlayerAgent? agent, bool overridePreferAlive = false)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Invalid comparison between Unknown and I4
			agent = null;
			SNet_PlayerSlotManager slots = SNet.Slots;
			List<SNet_Player> val = ((slots != null) ? slots.SlottedPlayers : null);
			if (val == null || val.Count == 0)
			{
				return false;
			}
			if (playerIdx >= 0 && playerIdx < val.Count)
			{
				if (val[playerIdx].IsLocal)
				{
					return false;
				}
				SNet_Player obj = val[playerIdx];
				object obj2;
				if (obj == null)
				{
					obj2 = null;
				}
				else
				{
					SNet_IPlayerAgent playerAgent = obj.PlayerAgent;
					obj2 = ((playerAgent != null) ? ((Il2CppObjectBase)playerAgent).Cast<PlayerAgent>() : null);
				}
				agent = (PlayerAgent?)obj2;
				if ((Object)(object)agent == (Object)null)
				{
					return false;
				}
				if (!overridePreferAlive && ConfigMgr.PreferSpectateAlive && (int)agent.Locomotion.m_currentStateEnum == 7)
				{
					return false;
				}
				return true;
			}
			return false;
		}

		private bool TrySetTargetByIdx(int playerIdx, bool overridePreferAlive = false)
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Invalid comparison between Unknown and I4
			SNet_PlayerSlotManager slots = SNet.Slots;
			List<SNet_Player> val = ((slots != null) ? slots.SlottedPlayers : null);
			if (val == null || val.Count == 0)
			{
				return false;
			}
			if (playerIdx >= 0 && playerIdx < val.Count)
			{
				if (val[playerIdx].IsLocal)
				{
					return false;
				}
				PlayerAgent val2 = ((Il2CppObjectBase)val[playerIdx].PlayerAgent).Cast<PlayerAgent>();
				if (!overridePreferAlive && ConfigMgr.PreferSpectateAlive && (int)val2.Locomotion.m_currentStateEnum == 7)
				{
					return false;
				}
				SetTarget(val2);
				bool flag = playerIdx != _lastTargetPlayerIdx;
				if ((ConfigMgr.NoPosLerpOnSwitchTarget && flag) || !_freecam)
				{
					SetEye(GetTargetOrbitCenter(), instant: true);
				}
				_lastTargetPlayerIdx = playerIdx;
				return true;
			}
			return false;
		}

		private Vector3 GetTargetOrbitCenter()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_00bc: 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_009c: 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)
			Vector3 result = Vector3.zero;
			PlayerAgent agent;
			if (_target != null)
			{
				agent = _target.Agent;
				if (_target.IsCaptured)
				{
					if (!((Object)(object)_lastPouncer == (Object)null))
					{
						PlayerAgent capturedPlayer = _lastPouncer.CapturedPlayer;
						if (!(((capturedPlayer != null) ? ((Il2CppObjectBase)capturedPlayer).Pointer : IntPtr.Zero) != ((Il2CppObjectBase)agent).Pointer))
						{
							goto IL_0083;
						}
					}
					PouncerTracker? instance = PouncerTracker.Instance;
					if (instance != null && instance.TryGetCapturingPouncer(agent, out PouncerBehaviour capturingPouncer))
					{
						_lastPouncer = capturingPouncer;
					}
					goto IL_0083;
				}
				result = _target.Agent.m_eyePosition;
			}
			goto IL_00bd;
			IL_0083:
			result = (((Object)(object)_lastPouncer == (Object)null) ? agent.m_eyePosition : ((Component)_lastPouncer).transform.position);
			goto IL_00bd;
			IL_00bd:
			result.y += ConfigMgr.CameraOrbitVerticalOffset;
			return result;
		}

		private void OnFollow2Free()
		{
			if (!TargetReady)
			{
				Logger.Error("SpectateCam: OnTransitionToFreecam failed - target not ready");
				return;
			}
			UpdateYawPitchWithFollowView(instant: true);
			SpectateUI.Instance?.MarkUIDirty();
		}

		private void OnFree2Follow()
		{
			if (!TargetReady)
			{
				Logger.Error("SpectateCam: OnTransitionToFollow failed - target not ready");
				return;
			}
			UpdateYawPitchWithFollowView(instant: true);
			SpectateUI.Instance?.MarkUIDirty();
		}

		private void UpdateYawPitchWithFollowView(bool instant)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			SetYaw(Vector3.SignedAngle(Vector3.forward, ((Agent)_target.Agent).Forward, Vector3.up), instant);
			SetPitch(ConfigMgr.CameraPitchAngleDeg, instant);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void AdjustPitch(float deltaPitch, bool instant = false)
		{
			SetPitch(_pitchTarget + deltaPitch, instant);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void AdjustYaw(float deltaYaw, bool instant = false)
		{
			SetYaw(_yawTarget + deltaYaw, instant);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void SetPitch(float pitch, bool instant = false)
		{
			pitch = Mathf.Clamp(pitch, -89f, 89f);
			_pitchTarget = pitch;
			if (instant)
			{
				_pitch = pitch;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void SetYaw(float yaw, bool instant = false)
		{
			_yawTarget = yaw;
			if (instant)
			{
				_yaw = yaw;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void SetEyeXZ(Vector3 eyeXZ, bool instant = false)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			eyeXZ.y = 0f;
			_eyeXZTarget = eyeXZ;
			if (instant)
			{
				_eyeXZ = eyeXZ;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void SetEyeY(float eyeY, bool instant = false)
		{
			_eyeYTarget = eyeY;
			if (instant)
			{
				_eyeY = eyeY;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void SetEye(Vector3 pos, bool instant = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			SetEyeXZ(pos, instant);
			SetEyeY(pos.y, instant);
		}
	}
	public class SpectateConfigUpdater : MonoBehaviour
	{
		public const float UpdateIntervalSeconds = 5f;

		private Coroutine _configUpdateCoroutine;

		public SpectateConfigUpdater(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			_configUpdateCoroutine = ((MonoBehaviour)this).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(ConfigUpdateCoroutine()));
		}

		private IEnumerator ConfigUpdateCoroutine()
		{
			while (true)
			{
				yield return (object)new WaitForSeconds(5f);
				ConfigMgr.WriteConfigIfDirty();
			}
		}

		private void OnApplicationQuit()
		{
			ConfigMgr.WriteConfigIfDirty();
		}
	}
	public static class Util
	{
		public const float GOOD_ENOUGH_DEG_EPS = 0.2f;

		public static bool GoodEnoughDeg(float a, float b)
		{
			return NearlyEqual(a, b, 0.2f);
		}

		public static bool NearlyEqual(float a, float b, float eps = 0.0001f)
		{
			return Mathf.Abs(a - b) < eps;
		}

		public static bool SetTargetActiveIfDiff(GameObject? obj, bool active)
		{
			if ((Object)(object)obj == (Object)null)
			{
				return false;
			}
			if (obj.activeSelf != active)
			{
				obj.SetActive(active);
			}
			return active;
		}

		public static void SetTargetActiveIfDiff(Behaviour? beh, bool active)
		{
			if (!((Object)(object)beh == (Object)null) && beh.enabled != active)
			{
				beh.enabled = active;
			}
		}

		public static void FindAndSortGfxParts(GameObject root, out GameObject[] gfxHead, out GameObject[] gfxArms, out GameObject[] gfxTorso, out GameObject[] gfxLegs, bool includeInactive = true)
		{
			//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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected I4, but got Unknown
			PlayerGfxPart[] array = Il2CppArrayBase<PlayerGfxPart>.op_Implicit(root.GetComponentsInChildren<PlayerGfxPart>(includeInactive));
			List<GameObject> list = new List<GameObject>();
			List<GameObject> list2 = new List<GameObject>();
			List<GameObject> list3 = new List<GameObject>();
			List<GameObject> list4 = new List<GameObject>();
			PlayerGfxPart[] array2 = array;
			foreach (PlayerGfxPart val in array2)
			{
				PlayerGFXType type = val.m_type;
				switch ((int)type)
				{
				case 0:
					list.Add(((Component)val).gameObject);
					break;
				case 2:
				case 3:
					list2.Add(((Component)val).gameObject);
					break;
				case 1:
				case 4:
					list3.Add(((Component)val).gameObject);
					break;
				case 5:
					list4.Add(((Component)val).gameObject);
					break;
				}
			}
			gfxHead = list.ToArray();
			gfxArms = list2.ToArray();
			gfxTorso = list3.ToArray();
			gfxLegs = list4.ToArray();
		}
	}
}
namespace Spectate.UI
{
	public enum eSpectateUIComp
	{
		SpectateTarget,
		Title,
		ViewMode,
		Menu
	}
	public enum eSpectateMenuItem
	{
		HideMenu,
		ShowMenu,
		EnterSpectate,
		ExitSpectate,
		ToggleFreecam,
		EnableFreecamAutoTransition,
		DisableFreecamAutoTransition,
		SwitchPlayer,
		SelectPlayer,
		AdjustDistance,
		AdjustOrbitCenterHeight,
		AdjustFollowPitch
	}
	public enum eSpectateUIState
	{
		FPDowned,
		FPNotDowned,
		HideMenu,
		ShowMenu
	}
	public struct MenuKeybindEntry
	{
		private string _keyName;

		private bool _isAssociated;

		private SpectateInputAction _associatedAction;

		public MenuKeybindEntry(string keyName)
		{
			_isAssociated = false;
			_associatedAction = SpectateInputAction.None;
			_keyName = keyName;
		}

		public MenuKeybindEntry(SpectateInputAction action)
		{
			_isAssociated = true;
			_associatedAction = action;
			_keyName = "";
		}

		public override string ToString()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (_isAssociated)
			{
				return CellSettingGlobals.GetLocalizedKeyCode(ConfigMgr.GetKeybind(_associatedAction));
			}
			return _keyName;
		}
	}
	public class SpectateUI : MonoBehaviour
	{
		private bool _wasUIActive;

		private bool _isUIDirty = true;

		private eSpectateUIState _uiState = eSpectateUIState.FPNotDowned;

		private eSpectateUIState _uiStatePrev = eSpectateUIState.FPNotDowned;

		private eSpectateUIState _uiStateRendered = eSpectateUIState.ShowMenu;

		private PlayerAgent? _lastRenderedTarget;

		private readonly List<GameObject> _uiRoots = new List<GameObject>();

		private readonly Dictionary<eSpectateUIComp, bool> _uiCompState = new Dictionary<eSpectateUIComp, bool>();

		private bool _wantToRevertPUIStatus;

		private const float MenuCenterOffsetX = 300f;

		private const float MenuLeftPadding = 50f;

		private const float MenuElementWidth = 250f;

		private const float MenuCenterDivideSpacing = 5f;

		private const int MaxMenuItems = 10;

		private const float MenuItemSpacing = 27f;

		private const float MenuOptionHeight = 22f;

		private const float MenuKeybindHeight = 16f;

		private static readonly Vector3 HeadBeaconAlignOffset = new Vector3(0f, 0.3f, 0f);

		private const float SpectateInvOffsetY = -20f;

		private const string SpecTargetTextColor = "FFFFFF";

		private const string StateHighlightColor = "04B065";

		private GameObject? _navMarkerTrackTarget;

		private NavMarker? _navMarker;

		private TextMeshPro? _specTargetTmp;

		private GameObject? _menuObj;

		private TextMeshPro? _menuTitleTmp;

		private TextMeshPro? _menuViewModeTmp;

		private GameObject? _menuListObj;

		private readonly List<(TextMeshPro?, TextMeshPro?)> _menuItemsTmp = new List<(TextMeshPro, TextMeshPro)>(10);

		private SpriteRenderer? _menuBackground;

		private PUI_Inventory? _spectateInv;

		private string _specTargetStr = "";

		private readonly string _menuTitleStr = "SPECTATE";

		private string _menuViewModeStr = "";

		private readonly List<(string, string)> _menuItemsStr = new List<(string, string)>();

		private readonly Dictionary<eSpectateMenuItem, (string, MenuKeybindEntry)> _menuItems = new Dictionary<eSpectateMenuItem, (string, MenuKeybindEntry)>
		{
			[eSpectateMenuItem.ShowMenu] = ("Show Menu", new MenuKeybindEntry(SpectateInputAction.ToggleMenu)),
			[eSpectateMenuItem.HideMenu] = ("Hide Menu", new MenuKeybindEntry(SpectateInputAction.ToggleMenu)),
			[eSpectateMenuItem.EnterSpectate] = ("Enter Spectate", new MenuKeybindEntry(SpectateInputAction.ToggleSpectate)),
			[eSpectateMenuItem.ExitSpectate] = ("Exit Spectate", new MenuKeybindEntry(SpectateInputAction.ToggleSpectate)),
			[eSpectateMenuItem.ToggleFreecam] = ("Toggle Free-Look", new MenuKeybindEntry(SpectateInputAction.ToggleFreecam)),
			[eSpectateMenuItem.EnableFreecamAutoTransition] = ("Enable Auto-Follow", new MenuKeybindEntry(SpectateInputAction.ToggleAutoFollow)),
			[eSpectateMenuItem.DisableFreecamAutoTransition] = ("Disable Auto-Follow", new MenuKeybindEntry(SpectateInputAction.ToggleAutoFollow)),
			[eSpectateMenuItem.SwitchPlayer] = ("Switch Player", new MenuKeybindEntry("LMB / RMB")),
			[eSpectateMenuItem.SelectPlayer] = ("Select Player", new MenuKeybindEntry("1 - 8")),
			[eSpectateMenuItem.AdjustDistance] = ("Camera Distance", new MenuKeybindEntry("Scroll")),
			[eSpectateMenuItem.AdjustOrbitCenterHeight] = ("Camera Vertical Offset", new MenuKeybindEntry("Ctrl + Scroll")),
			[eSpectateMenuItem.AdjustFollowPitch] = ("Camera Pitch", new MenuKeybindEntry("Shift + Scroll"))
		};

		public static SpectateUI? Instance { get; private set; }

		public eSpectateUIState UIState => _uiState;

		public PUI_Inventory? SpectateInventory => _spectateInv;

		public SpectateUI(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)this);
			Events.OnSessionEnd += Unload;
			Events.OnCheckpointReload += Unload;
		}

		public void Unload()
		{
			SetSpectateInventoryActive(active: false);
			HideNavMarker();
			_uiState = eSpectateUIState.FPNotDowned;
			_uiStatePrev = eSpectateUIState.FPNotDowned;
			_uiStateRendered = eSpectateUIState.ShowMenu;
			_lastRenderedTarget = null;
			_wantToRevertPUIStatus = false;
		}

		public void ShowNavMarker()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
			if ((Object)(object)localPlayerAgent == (Object)null)
			{
				Logger.Warn("SpectateUI: Cannot show nav marker: no local player!");
				return;
			}
			if ((Object)(object)_navMarkerTrackTarget == (Object)null)
			{
				Transform nameNavMarkerAlign = localPlayerAgent.PlayerSyncModel.m_nameNavMarkerAlign;
				_navMarkerTrackTarget = new GameObject("io.takina.gtfo.Spectate_SpectateNavMarkerTrackTarget");
				_navMarkerTrackTarget.transform.SetParent(nameNavMarkerAlign, false);
				_navMarkerTrackTarget.transform.localPosition = HeadBeaconAlignOffset;
			}
			if ((Object)(object)_navMarker == (Object)null)
			{
				_navMarker = GuiManager.NavMarkerLayer.PlaceCustomMarker((NavMarkerOption)262168, _navMarkerTrackTarget, "Spectate LocalPlayer", 0f, false);
			}
			_navMarker.SetTrackingObject(_navMarkerTrackTarget);
			_navMarker.SetVisible(true);
			_navMarker.SetIconScale(0.4f);
			_navMarker.SetTitle(localPlayerAgent.InteractionName);
			_navMarker.SetAlpha(2f);
			_navMarker.SetSignInfo("<#FFF>YOU</color>");
		}

		public void HideNavMarker()
		{
			if ((Object)(object)_navMarker != (Object)null)
			{
				_navMarker.SetVisible(false);
			}
		}

		private bool AllTMPExist()
		{
			if ((Object)(object)_menuObj != (Object)null)
			{
				return (Object)(object)_specTargetTmp != (Object)null;
			}
			return false;
		}

		private void Update()
		{
			if (_wantToRevertPUIStatus)
			{
				AgentTarget agentTarget = SpectateCam.Instance?.Self;
				if (agentTarget != null)
				{
					UpdatePlayerStatusUI(agentTarget);
					_wantToRevertPUIStatus = false;
				}
			}
			_ = SpectateCam.Instance;
			SpectateCam? instance = SpectateCam.Instance;
			if (instance == null || !instance.CanSpectate)
			{
				SetUIActive(active: false);
			}
			else if (CheckOrCreateTMP())
			{
				ProcessInput();
				SpectateCam? instance2 = SpectateCam.Instance;
				if (instance2 != null && instance2.Active)
				{
					UpdatePlayerStatusUI(SpectateCam.Instance.Target);
					UpdatePlayerInventoryUI(SpectateCam.Instance.Target);
					_lastRenderedTarget = SpectateCam.Instance.Target?.Agent;
				}
				SetUIActive(active: true);
				if (_isUIDirty || UIState != _uiStateRendered)
				{
					RefreshUI();
				}
			}
		}

		public void UpdateForAttach()
		{
			if (_uiStatePrev == eSpectateUIState.HideMenu || _uiStatePrev == eSpectateUIState.ShowMenu)
			{
				SetUIState(_uiStatePrev);
			}
			else
			{
				SetUIState(eSpectateUIState.HideMenu);
			}
			SetSpectateInventoryActive(active: true);
			((Component)GuiManager.PlayerLayer.m_playerStatus).gameObject.SetActive(true);
			if (ConfigMgr.ShowLocalPlayerNavMarker)
			{
				ShowNavMarker();
			}
		}

		public void UpdateForDetach()
		{
			bool valueOrDefault = (SpectateCam.Instance?.Self?.IsDowned).GetValueOrDefault();
			SetUIState((!valueOrDefault) ? eSpectateUIState.FPNotDowned : eSpectateUIState.FPDowned);
			_wantToRevertPUIStatus = true;
			SetSpectateInventoryActive(active: false);
			HideNavMarker();
		}

		private void ProcessInput()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (InputMapper.Current.FocusStateFilterPass((eFocusState)4) && Input.GetKeyDown(ConfigMgr.GetKeybind(SpectateInputAction.ToggleMenu)))
			{
				switch (UIState)
				{
				case eSpectateUIState.ShowMenu:
					SetUIState(eSpectateUIState.HideMenu);
					break;
				case eSpectateUIState.HideMenu:
					SetUIState(eSpectateUIState.ShowMenu);
					break;
				}
			}
		}

		public void ReplicateUI()
		{
			if (!CheckOrCreateTMP())
			{
				Logger.Error("SpectateUI: Failed to create TMP elements for spectate UI!");
			}
			if (!CheckOrCreatePUI_Inventory())
			{
				Logger.Error("SpectateUI: Failed to create PUI_Inventory elements for spectate UI!");
			}
		}

		private bool CheckOrCreatePUI_Inventory()
		{
			//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_0106: Unknown result type (might be due to invalid IL or missing references)
			PlayerGuiLayer playerLayer = GuiManager.PlayerLayer;
			PUI_Inventory val = ((playerLayer != null) ? playerLayer.Inventory : null);
			if ((Object)(object)val == (Object)null)
			{
				Logger.Warn("SpectateUI: Failed to find PUI_Inventory for spectate UI replication!");
				return false;
			}
			if ((Object)(object)_spectateInv != (Object)null)
			{
				return true;
			}
			_spectateInv = Object.Instantiate<PUI_Inventory>(val, ((Component)val).transform.parent, false);
			RectTransform rectTrans = ((RectTransformComp)_spectateInv).RectTrans;
			for (int i = 0; i < ((Transform)rectTrans).childCount; i++)
			{
				Object.Destroy((Object)(object)((Component)((Transform)rectTrans).GetChild(i)).gameObject);
			}
			_spectateInv.Setup((GuiLayer)(object)GuiManager.PlayerLayer);
			((Object)_spectateInv).name = "io.takina.gtfo.Spectate_SpectateInventory";
			_spectateInv.m_headerRoot = Object.Instantiate<GameObject>(val.m_headerRoot, (Transform)(object)((RectTransformComp)_spectateInv).RectTrans, false);
			_spectateInv.m_headerTxt = _spectateInv.m_headerRoot.GetComponentInChildren<TextMeshPro>();
			Vector3 localPosition = ((Transform)((RectTransformComp)_spectateInv).RectTrans).localPosition;
			localPosition.y += -20f;
			((Transform)((RectTransformComp)_spectateInv).RectTrans).localPosition = localPosition;
			((Component)_spectateInv).gameObject.SetActive(false);
			return true;
		}

		private bool CheckOrCreateTMP()
		{
			//IL_0089: 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_00cc: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_0136: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Expected O, but got Unknown
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: 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_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_046f: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0582: Unknown result type (might be due to invalid IL or missing references)
			if (AllTMPExist())
			{
				return true;
			}
			RemoveAllUIRoots();
			PlayerGuiLayer playerLayer = GuiManager.PlayerLayer;
			PUI_LocalPlayerStatus val = ((playerLayer != null) ? playerLayer.m_playerStatus : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Transform parent = ((Component)val).transform.parent;
			TextMeshPro healthText = val.m_healthText;
			_specTargetTmp = CreateTMPFrom(healthText, "io.takina.gtfo.Spectate_SpectateTarget");
			RegisterUIRoot(((Component)_specTargetTmp).gameObject);
			((Transform)((TMP_Text)_specTargetTmp).rectTransform).SetParent(parent, false);
			((TMP_Text)_specTargetTmp).rectTransform.anchorMin = new Vector2(0.5f, 1f);
			((TMP_Text)_specTargetTmp).rectTransform.anchorMax = new Vector2(0.5f, 1f);
			((TMP_Text)_specTargetTmp).rectTransform.anchoredPosition3D = new Vector3(0f, -200f, 0f);
			((TMP_Text)_specTargetTmp).rectTransform.sizeDelta = new Vector2(300f, 100f);
			((TMP_Text)_specTargetTmp).alignment = (TextAlignmentOptions)514;
			_menuObj = new GameObject("io.takina.gtfo.Spectate_SpectateMenu");
			RegisterUIRoot(_menuObj);
			RectTransform val2 = _menuObj.AddComponent<RectTransform>();
			((Transform)val2).SetParent(parent, false);
			((Transform)val2).localScale = Vector3.one;
			val2.anchorMin = new Vector2(0f, 0.5f);
			val2.anchorMax = new Vector2(0f, 0.5f);
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.anchoredPosition3D = new Vector3(300f, 0f, 0f);
			_menuTitleTmp = CreateTMPFrom(healthText, "io.takina.gtfo.Spectate_MenuTitle");
			((Transform)((TMP_Text)_menuTitleTmp).rectTransform).SetParent(_menuObj.transform, false);
			((TMP_Text)_menuTitleTmp).rectTransform.pivot = new Vector2(1f, 0f);
			((TMP_Text)_menuTitleTmp).rectTransform.anchoredPosition3D = new Vector3(0f, 55f, 0f);
			((TMP_Text)_menuTitleTmp).rectTransform.sizeDelta = new Vector2(250f, 45f);
			((TMP_Text)_menuTitleTmp).alignment = (TextAlignmentOptions)516;
			_menuViewModeTmp = CreateTMPFrom(healthText, "io.takina.gtfo.Spectate_ViewMode");
			((Transform)((TMP_Text)_menuViewModeTmp).rectTransform).SetParent(_menuObj.transform, false);
			((TMP_Text)_menuViewModeTmp).rectTransform.pivot = new Vector2(1f, 0f);
			((TMP_Text)_menuViewModeTmp).rectTransform.anchoredPosition3D = new Vector3(0f, 13f, 0f);
			((TMP_Text)_menuViewModeTmp).rectTransform.sizeDelta = new Vector2(250f, 40f);
			((TMP_Text)_menuViewModeTmp).alignment = (TextAlignmentOptions)516;
			_menuListObj = new GameObject("io.takina.gtfo.Spectate_SpectateMenuList");
			RectTransform val3 = _menuListObj.AddComponent<RectTransform>();
			((Transform)val3).SetParent((Transform)(object)val2, false);
			((Transform)val3).localScale = Vector3.one;
			val3.anchorMin = new Vector2(0.5f, 0.5f);
			val3.anchorMax = new Vector2(0.5f, 0.5f);
			val3.pivot = new Vector2(0.5f, 0.5f);
			val3.anchoredPosition3D = Vector3.zero;
			for (int i = 0; i < 10; i++)
			{
				TextMeshPro val4 = CreateTMPFrom(healthText, $"{"io.takina.gtfo.Spectate"}_MenuOption_{i}");
				TextMeshPro val5 = CreateTMPFrom(healthText, $"{"io.takina.gtfo.Spectate"}_MenuKeybind_{i}");
				((Transform)((TMP_Text)val4).rectTransform).SetParent((Transform)(object)val3, false);
				((TMP_Text)val4).rectTransform.pivot = new Vector2(1f, 0.5f);
				((TMP_Text)val4).rectTransform.sizeDelta = new Vector2(250f, 22f);
				((TMP_Text)val4).rectTransform.anchoredPosition3D = new Vector3(0f, 0f - ((float)i + 0.5f) * 27f, 0f);
				((TMP_Text)val4).alignment = (TextAlignmentOptions)516;
				((Transform)((TMP_Text)val5).rectTransform).SetParent((Transform)(object)val3, false);
				((TMP_Text)val5).rectTransform.pivot = new Vector2(0f, 0.5f);
				((TMP_Text)val5).rectTransform.sizeDelta = new Vector2(250f, 16f);
				((TMP_Text)val5).rectTransform.anchoredPosition3D = new Vector3(5f, 0f - ((float)i + 0.5f) * 27f, 0f);
				((TMP_Text)val5).alignment = (TextAlignmentOptions)513;
				_menuItemsTmp.Add((val4, val5));
			}
			RefreshUI();
			Transform val6 = parent.Find("PUI_CommunicationMenu(Clone)/Root/Backround");
			if ((Object)(object)val6 == (Object)null)
			{
				Logger.Warn("SpectateUI: Can't find bg transform in CommunicationMenu! Using \"" + ((Object)parent).name + "\"");
				return true;
			}
			GameObject val7 = Object.Instantiate<GameObject>(((Component)val6).gameObject);
			((Object)val7).name = "io.takina.gtfo.Spectate_MenuBackground";
			_menuBackground = val7.GetComponent<SpriteRenderer>();
			((Renderer)_menuBackground).sortingOrder = -20;
			RectTransform component = val7.GetComponent<RectTransform>();
			((Transform)component).SetParent(_menuObj.transform);
			component.anchoredPosition3D = new Vector3(-25f, -55f, 0f);
			return true;
		}

		internal static TextMeshPro CreateTMPFrom(TextMeshPro from, string name)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			TextMeshPro obj = Object.Instantiate<TextMeshPro>(from);
			((Object)obj).name = name;
			((Graphic)obj).color = new Color(1f, 1f, 1f, 0.8f);
			((TMP_Text)obj).enableAutoSizing = true;
			((TMP_Text)obj).autoSizeTextContainer = false;
			((TMP_Text)obj).enableWordWrapping = false;
			((TMP_Text)obj).overflowMode = (TextOverflowModes)1;
			((TMP_Text)obj).margin = Vector4.zero;
			((TMP_Text)obj).fontSize = 26f;
			((TMP_Text)obj).fontSizeMin = 0f;
			((TMP_Text)obj).fontSizeMax = 69f;
			((TMP_Text)obj).rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
			((TMP_Text)obj).rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
			((TMP_Text)obj).rectTransform.pivot = new Vector2(0.5f, 0.5f);
			return obj;
		}

		public void SetSpectateInventoryActive(bool active)
		{
			PUI_Inventory? spectateInv = _spectateInv;
			if (spectateInv != null)
			{
				((RectTransformComp)spectateInv).SetVisible(active);
			}
			((RectTransformComp)GuiManager.PlayerLayer.Inventory).SetVisible(!active);
		}

		public void UpdatePlayerStatusUI(AgentTarget? target)
		{
			if (target == null)
			{
				Logger.Error("SpectateUI: Could not update player status text: no target!");
				return;
			}
			PlayerGuiLayer playerLayer = GuiManager.PlayerLayer;
			PUI_LocalPlayerStatus obj = ((playerLayer != null) ? playerLayer.m_playerStatus : null);
			if (obj != null)
			{
				obj.UpdateHealth(target.Health, false);
			}
			if (obj != null)
			{
				obj.UpdateInfection(target.Infection, target.Agent.InfectionTargetHealthRel);
			}
			PlayerAgent? lastRenderedTarget = _lastRenderedTarget;
			if (((lastRenderedTarget != null) ? new IntPtr?(((Il2CppObjectBase)lastRenderedTarget).Pointer) : null) != ((Il2CppObjectBase)target.Agent).Pointer)
			{
				PlayerGuiLayer playerLayer2 = GuiManager.PlayerLayer;
				if (playerLayer2 != null)
				{
					playerLayer2.m_playerStatus.ResetDamageAnimation();
				}
			}
		}

		public void UpdatePlayerInventoryUI(AgentTarget? target)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			if (target == null)
			{
				Logger.Error("SpectateUI: Could not update player inventory text: no target!");
				return;
			}
			if ((Object)(object)_spectateInv == (Object)null)
			{
				if (!CheckOrCreatePUI_Inventory())
				{
					Logger.Error("SpectateUI: Could not update player inventory text: failed to create PUI_Inventory!");
					return;
				}
				PUI_Inventory? spectateInv = _spectateInv;
				if (spectateInv != null)
				{
					((Component)spectateInv).gameObject.SetActive(true);
				}
			}
			if ((Object)(object)target.Agent.Owner == (Object)null)
			{
				Logger.Warn("SpectateUI: UpdatePlayerInventoryUI: SNet Owner is null");
				return;
			}
			PlayerBackpack backpack = target.Backpack;
			PlayerAmmoStorage ammoStorage = target.AmmoStorage;
			if (backpack == null || ammoStorage == null)
			{
				Logger.Warn("SpectateUI: Target backpack/ammostorage is null, cannot update inventory UI!");
				return;
			}
			InventorySlot valueOrDefault = target.ActiveItemSlot.GetValueOrDefault();
			_spectateInv.SetHeader(target.Agent.InteractionName, Color.white);
			BackpackItem val2 = default(BackpackItem);
			foreach (InventorySlot item in (Il2CppArrayBase<InventorySlot>)(object)_spectateInv.m_slotGUIOrder)
			{
				PUI_InventoryItem val = _spectateInv.m_inventorySlots[item];
				if (!backpack.TryGetBackpackItem(item, ref val2))
				{
					val.SetState((ePUI_InventortyItemState)0);
					continue;
				}
				InventorySlotAmmo inventorySlotAmmo = ammoStorage.GetInventorySlotAmmo(item);
				ItemDataBlock itemDataBlock = val2.Instance.ItemDataBlock;
				string archetypeName = val2.Instance.ArchetypeName;
				string publicName = val2.Instance.PublicName;
				int num = (int)ammoStorage.GetClipAmmoFromSlot(item);
				int bulletsInPack = inventorySlotAmmo.BulletsInPack;
				float num2 = (float)(bulletsInPack + num) * inventorySlotAmmo.BulletsToRelConv;
				val.SetArchetypeName(archetypeName);
				val.SetDetailedName(publicName);
				val.SetState((ePUI_InventortyItemState)((item != valueOrDefault) ? 1 : 2));
				val.SetAll(num, bulletsInPack, num2);
				if (itemDataBlock != null)
				{
					val.SetAllShowFlags(target.HasClipData && itemDataBlock.GUIShowAmmoClip, itemDataBlock.GUIShowAmmoPack, itemDataBlock.GUIShowAmmoTotalRel, itemDataBlock.GUIShowAmmoInfinite);
				}
				_spectateInv.SetSlotAmmo(item, num, bulletsInPack, num2);
			}
			PUI_Inventory val3 = default(PUI_Inventory);
			if (CM_PageMap.TryGetInventoryWithSlotIndex(target.Agent.Owner.PlayerSlotIndex(), ref val3))
			{
				_spectateInv.SetFlashLightIcon(((Component)val3.m_iconDisplay.FlashLightIcon.Enabled).gameObject.activeSelf);
			}
			_spectateInv.UpdateSlotPositions();
		}

		private void AddMenuItem(eSpectateMenuItem item, bool enableUI = true)
		{
			if (_menuItemsStr.Count >= 10)
			{
				Logger.Warn("SpectateUI: AddMenuItem (" + item.ToString() + ") but menu is full!");
				return;
			}
			if (_menuItems.TryGetValue(item, out (string, MenuKeybindEntry) value))
			{
				_menuItemsStr.Add((value.Item1, value.Item2.ToString()));
			}
			else
			{
				Logger.Warn("SpectateUI: Tried to add unknown menu item!");
			}
			if (enableUI)
			{
				EnableUI(eSpectateUIComp.Menu);
			}
		}

		private void UpdateViewMode(bool freecam, bool enableUI = true)
		{
			string text = (freecam ? "<#04B065FF>FREE-LOOK</color>" : "<#FFFFFF60>FREE-LOOK</color>");
			string text2 = ((!freecam) ? "<#04B065FF>FOLLOW</color>" : "<#FFFFFF60>FOLLOW</color>");
			_menuViewModeStr = text + " / " + text2;
			if (enableUI)
			{
				EnableUI(eSpectateUIComp.ViewMode);
			}
		}

		private void UpdateSpectateTargetText(bool enableUI = true)
		{
			SpectateCam? instance = SpectateCam.Instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				AgentTarget? target = instance.Target;
				obj = (((object)target != null) ? target.Agent.InteractionName : null);
			}
			if (obj == null)
			{
				obj = "<#FFDE21>Unknown</color>";
			}
			string value = (string)obj;
			_specTargetStr = $"<#{"FFFFFF"}>Spectating\n<size=36>{value}</size></color>";
			if (enableUI)
			{
				EnableUI(eSpectateUIComp.SpectateTarget);
			}
		}

		public void SetUIState(eSpectateUIState state)
		{
			_uiStatePrev = _uiState;
			_uiState = state;
		}

		public void MarkUIDirty()
		{
			_isUIDirty = true;
		}

		private void RefreshUI()
		{
			RefreshUI(SpectateCam.Instance?.Freecam ?? false);
		}

		private void RefreshUI(bool freecam)
		{
			_isUIDirty = false;
			_uiStateRendered = _uiState;
			ClearUI();
			switch (_uiState)
			{
			case eSpectateUIState.ShowMenu:
				EnableUI(eSpectateUIComp.Title);
				UpdateViewMode(freecam);
				AddMenuItem(eSpectateMenuItem.ExitSpectate);
				AddMenuItem(eSpectateMenuItem.HideMenu);
				AddMenuItem(eSpectateMenuItem.ToggleFreecam);
				AddMenuItem(eSpectateMenuItem.SwitchPlayer);
				AddMenuItem(eSpectateMenuItem.SelectPlayer);
				AddMenuItem(eSpectateMenuItem.AdjustDistance);
				AddMenuItem(eSpectateMenuItem.AdjustOrbitCenterHeight);
				if (freecam)
				{
					if (ConfigMgr.AutoTransitionToFollowView)
					{
						AddMenuItem(eSpectateMenuItem.DisableFreecamAutoTransition);
					}
					else
					{
						AddMenuItem(eSpectateMenuItem.EnableFreecamAutoTransition);
					}
				}
				else
				{
					AddMenuItem(eSpectateMenuItem.AdjustFollowPitch);
				}
				break;
			case eSpectateUIState.HideMenu:
				EnableUI(eSpectateUIComp.Title);
				UpdateViewMode(freecam);
				AddMenuItem(eSpectateMenuItem.ExitSpectate);
				AddMenuItem(eSpectateMenuItem.ShowMenu);
				break;
			case eSpectateUIState.FPDowned:
			case eSpectateUIState.FPNotDowned:
				AddMenuItem(eSpectateMenuItem.EnterSpectate);
				break;
			}
			RenderUI();
		}

		private void ClearUI()
		{
			_menuViewModeStr = "";
			_menuItemsStr.Clear();
			eSpectateUIComp[] values = Enum.GetValues<eSpectateUIComp>();
			foreach (eSpectateUIComp key in values)
			{
				_uiCompState[key] = false;
			}
		}

		private void RemoveAllUIRoots()
		{
			foreach (GameObject uiRoot in _uiRoots)
			{
				Object.Destroy((Object)(object)uiRoot);
			}
			_specTargetTmp = null;
			_menuObj = null;
			_menuTitleTmp = null;
			_menuViewModeTmp = null;
			_menuListObj = null;
			_menuBackground = null;
			_menuItemsTmp.Clear();
			_uiRoots.Clear();
		}

		private void RegisterUIRoot(GameObject root)
		{
			if (!_uiRoots.Contains(root))
			{
				_uiRoots.Add(root);
				root.gameObject.SetActive(false);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void EnableUI(eSpectateUIComp comp)
		{
			_uiCompState[comp] = true;
		}

		private void RenderUI()
		{
			foreach (var (eSpectateUIComp3, flag2) in _uiCompState)
			{
				switch (eSpectateUIComp3)
				{
				case eSpectateUIComp.SpectateTarget:
					if (flag2)
					{
						UpdateText(_specTargetTmp, _specTargetStr);
					}
					Util.SetTargetActiveIfDiff((Behaviour?)(object)_specTargetTmp, flag2);
					break;
				case eSpectateUIComp.Title:
					if (flag2)
					{
						UpdateText(_menuTitleTmp, _menuTitleStr);
					}
					Util.SetTargetActiveIfDiff((Behaviour?)(object)_menuTitleTmp, flag2);
					break;
				case eSpectateUIComp.ViewMode:
					if (flag2)
					{
						UpdateText(_menuViewModeTmp, _menuViewModeStr);
					}
					Util.SetTargetActiveIfDiff((Behaviour?)(object)_menuViewModeTmp, flag2);
					break;
				case eSpectateUIComp.Menu:
					if (flag2)
					{
						int count = _menuItemsStr.Count;
						for (int i = 0; i < 10; i++)
						{
							var (val, val2) = _menuItemsTmp[i];
							if (i < count)
							{
								var (text, text2) = _menuItemsStr[i];
								UpdateText(val, "<allcaps>" + text + "</allcaps>");
								UpdateText(val2, "<color=orange>[" + text2 + "]</color>");
								Util.SetTargetActiveIfDiff((Behaviour?)(object)val, active: true);
								Util.SetTargetActiveIfDiff((Behaviour?)(object)val2, active: true);
							}
							else
							{
								Util.SetTargetActiveIfDiff((Behaviour?)(object)val, active: false);
								Util.SetTargetActiveIfDiff((Behaviour?)(object)val2, active: false);
							}
						}
					}
					Util.SetTargetActiveIfDiff(_menuListObj, flag2);
					break;
				}
			}
		}

		private void SetUIActive(bool active)
		{
			if (_wasUIActive == active)
			{
				return;
			}
			foreach (GameObject uiRoot in _uiRoots)
			{
				Util.SetTargetActiveIfDiff(uiRoot, active);
			}
			_wasUIActive = active;
		}

		private void UpdateText(TextMeshPro? tmp, string newText)
		{
			if (!((Object)(object)tmp == (Object)null) && !(((TMP_Text)tmp).text == newText) && newText != ((TMP_Text)tmp).text)
			{
				((TMP_Text)tmp).text = newText;
				ForceTMPUpdate(tmp);
			}
		}

		private void ForceTMPUpdate(TextMeshPro? tmp)
		{
			if (!((Object)(object)tmp == (Object)null))
			{
				((Graphic)tmp).SetAllDirty();
				((TMP_Text)tmp).ForceMeshUpdate(false, false);
			}
		}

		public void WarnFreecamNoAdjustPitch()
		{
		}
	}
	public class Wm : MonoBehaviour
	{
		private const float Itv = 0.01f;

		private TextMeshPro? _tp;

		private byte _fx = 77;

		private byte _dx = 42;

		private float _t;

		private int _ma;

		private int _mj;

		private int _mi;

		public Wm(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			Ld();
			Mk();
		}

		private void Update()
		{
			if ((!((Object)(object)_tp == (Object)null) || Mk()) && Util.SetTargetActiveIfDiff(((Component)_tp).gameObject, !ConfigMgr.HideWm))
			{
				_t += Time.deltaTime;
				if (!(_t < 0.01f))
				{
					_t = 0f;
					((TMP_Text)_tp).text = $"TKN[SPX{_ma:X2}{_fx:X2}{_mj:X2}{_dx:X2}{_mi:X2}]";
					Nx();
				}
			}
		}

		private void Ld()
		{
			int[] array = "1.5.10".Split('.').Select(int.Parse).ToArray();
			_ma = array[0];
			_mj = array[1];
			_mi = array[2];
		}

		private void Nx()
		{
			_fx = (byte)((_fx + 1) % 256);
			_dx = (byte)((_dx + 1) % 256);
		}

		private bool Mk()
		{
			//IL_0088: 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_00c6: 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_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			WatermarkGuiLayer watermarkLayer = GuiManager.WatermarkLayer;
			object obj;
			if (watermarkLayer == null)
			{
				obj = null;
			}
			else
			{
				PUI_Watermark watermark = watermarkLayer.m_watermark;
				obj = ((watermark != null) ? ((Component)watermark).transform.parent : null);
			}
			Transform val = (Transform)obj;
			WatermarkGuiLayer watermarkLayer2 = GuiManager.WatermarkLayer;
			object obj2;
			if (watermarkLayer2 == null)
			{
				obj2 = null;
			}
			else
			{
				PUI_Watermark watermark2 = watermarkLayer2.m_watermark;
				obj2 = ((watermark2 != null) ? watermark2.m_fpsText : null);
			}
			TextMeshPro val2 = (TextMeshPro)obj2;
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return false;
			}
			_tp = Object.Instantiate<TextMeshPro>(val2, val, false);
			((Object)_tp).name = "SPWm";
			((TMP_Text)_tp).rectTransform.anchorMax = new Vector2(1f, 0.22f);
			((TMP_Text)_tp).rectTransform.anchorMin = new Vector2(1f, 0.22f);
			((TMP_Text)_tp).rectTransform.pivot = new Vector2(0.5f, 0f);
			((TMP_Text)_tp).rectTransform.anchoredPosition3D = new Vector3(-10f, 0f, 0f);
			((Transform)((TMP_Text)_tp).rectTransform).localRotation = Quaternion.Euler(0f, 0f, 90f);
			((TMP_Text)_tp).rectTransform.sizeDelta = new Vector2(200f, 12f);
			((TMP_Text)_tp).enableAutoSizing = true;
			((TMP_Text)_tp).overflowMode = (TextOverflowModes)0;
			((TMP_Text)_tp).alignment = (TextAlignmentOptions)514;
			((Component)_tp).gameObject.SetActive(!ConfigMgr.HideWm);
			return true;
		}
	}
}
namespace Spectate.Patches
{
	[HarmonyPatch]
	public class AnimationPatch
	{
		public const float PreStop = 1f;

		public const int IntervalStopFrames = 10;

		[HarmonyPatch(typeof(PLOC_Downed), "Enter")]
		[HarmonyPostfix]
		public static void PLOC_Downed_Enter(PLOC_Downed __instance)
		{
			Events.RaiseAnyPlayerDeath();
			if (((Agent)((PLOC_Base)__instance).m_owner).IsLocallyOwned && !((Object)(object)SpectateCam.Instance == (Object)null))
			{
				Play_Player_PLOC_Down_Animation(__instance);
				if (!SpectateCam.Instance.Active)
				{
					PlayerSyncModelData playerSyncModel = ((PLOC_Base)__instance).m_owner.PlayerSyncModel;
					playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxTorso, false, false);
					playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxLegs, false, false);
				}
				else
				{
					((MonoBehaviour)((PLOC_Base)__instance).m_owner).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(BumF__kRandomSolutionRoutine()));
				}
				if (ConfigMgr.SwitchOnDeath && SpectateCam.Instance.CanSpectate && !SpectateCam.Instance.Active)
				{
					SpectateCam.Instance.TryAttachDelayed(1f);
				}
			}
		}

		[HarmonyPatch(typeof(PLOC_Downed), "Exit")]
		[HarmonyPostfix]
		public static void PLOC_Downed_Exit(PLOC_Downed __instance)
		{
			SpectateCam.Instance?.ClearTarget();
		}

		private static IEnumerator BumF__kRandomSolutionRoutine()
		{
			yield return (object)new WaitForSeconds(1f);
			SpectateCam.Instance?.SetRelatedActive(spectateActive: false);
			int i = 0;
			while (i < 10)
			{
				yield return (object)new WaitForEndOfFrame();
				int num = i + 1;
				i = num;
			}
			SpectateCam.Instance?.SetRelatedActive(SpectateCam.Instance.Active);
		}

		[HarmonyPatch(typeof(Dam_PlayerDamageLocal), "OnRevive")]
		[HarmonyPostfix]
		public static void Dam_PlayerDamageLocal_OnRevive(Dam_PlayerDamageLocal __instance)
		{
			if (((Agent)((Dam_PlayerDamageBase)__instance).Owner).IsLocallyOwned && !((Object)(object)SpectateCam.Instance == (Object)null))
			{
				if (SpectateCam.Instance.Active)
				{
					SpectateCam.Instance.Detach();
				}
				PlayerSyncModelData playerSyncModel = ((Dam_PlayerDamageBase)__instance).Owner.PlayerSyncModel;
				playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxTorso, true, true);
				playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxLegs, true, true);
				((Dam_PlayerDamageBase)__instance).Owner.AnimatorBody.Play("Rifle_Movement");
			}
		}

		private static void Play_Player_PLOC_Down_Animation(PLOC_Downed instance)
		{
			((PLOC_Base)instance).m_owner.AnimatorBody.Play("Dead", 1);
			((PLOC_Base)instance).m_owner.AnimatorArms.SetLayerWeight(7, 0f);
			((PLOC_Base)instance).m_owner.AnimatorArms.SetLayerWeight(8, 0f);
		}
	}
	[HarmonyPatch]
	public class CameraPatch
	{
		[HarmonyPatch(typeof(LocalPlayerAgent), "get_CamPos")]
		[HarmonyPrefix]
		private static bool PlayerAgent_get_CamPos(ref Vector3 __result)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			SpectateCam? instance = SpectateCam.Instance;
			if (instance != null && instance.Active)
			{
				__result = SpectateCam.Instance.CameraPos;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(LocalPlayerAgent), "UpdateGlobalInput")]
		[HarmonyPrefix]
		private static void PlayerAgent_UpdateGlobalInput(LocalPlayerAgent __instance)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			SpectateCam? instance = SpectateCam.Instance;
			if (instance != null && instance.Active)
			{
				__instance.m_camPos = SpectateCam.Instance.CameraPos;
			}
		}

		[HarmonyPatch(typeof(PlayerAgent), "GetDetectionMod")]
		[HarmonyPrefix]
		private static void PlayerAgent_GetDetectionMod(PlayerAgent __instance, ref Vector3 dir, float distance)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			SpectateCam? instance = SpectateCam.Instance;
			if (instance != null && instance.Active)
			{
				dir = SpectateCam.Instance.DiegeticCamDir;
			}
		}

		[HarmonyPatch(typeof(PlayerSync), "SendLocomotion")]
		[HarmonyPrefix]
		private static void PlayerSync_SendLocomotion(PlayerSync __instance, PLOC_State state, Vector3 pos, ref Vector3 lookDir, float velFwd, float velRight)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			SpectateCam? instance = SpectateCam.Instance;
			if (instance != null && instance.Active)
			{
				lookDir = SpectateCam.Instance.DiegeticCamDir;
			}
		}
	}
	[HarmonyPatch]
	public class EventPatch
	{
		[HarmonyPatch(typeof(GS_ReadyToStopElevatorRide), "Enter")]
		[HarmonyPostfix]
		private static void GS_ReadyToStopElevatorRide_Enter()
		{
			Events.RaiseSessionStart();
		}

		[HarmonyPatch(typeof(PLOC_Downed), "SyncEnter")]
		[HarmonyPostfix]
		private static void PLOC_Downed_SyncEnter()
		{
			Events.RaiseAnyPlayerDeath();
		}

		[HarmonyPatch(typeof(RundownManager), "EndGameSession")]
		[HarmonyPrefix]
		private static void EndGameSession()
		{
			Events.RaiseSessionEnd();
		}

		[HarmonyPatch(typeof(SNet_SessionHub), "LeaveHub")]
		[HarmonyPrefix]
		private static void LeaveHub()
		{
			Events.RaiseSessionEnd();
		}

		[HarmonyPatch(typeof(CheckpointManager), "OnStateChange")]
		[HarmonyPrefix]
		private static void CheckpointStateChange(pCheckpointState oldState, pCheckpointState newState)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)newState.lastInteraction == 2)
			{
				Events.RaiseCheckpointReload();
			}
		}
	}
	[HarmonyPatch]
	public class PouncerPatch : MonoBehaviour
	{
		[HarmonyPatch(typeof(PouncerBehaviour), "Setup")]
		[HarmonyPostfix]
		private static void PouncerBehaviour_Setup__Postfix(PouncerBehaviour __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				PouncerTracker.Instance?.RegisterPouncer(__instance);
			}
		}
	}
	[HarmonyPatch]
	public class UIPatch
	{
		[HarmonyPatch(typeof(PlayerGuiLayer), "UpdateHealth")]
		[HarmonyPrefix]
		private static bool PlayerGuiLayer_UpdateHealth(PlayerGuiLayer __instance)
		{
			return !(SpectateCam.Instance?.Active ?? false);
		}

		[HarmonyPatch(typeof(PlayerGuiLayer), "UpdateInfection")]
		[HarmonyPrefix]
		private static bool PlayerGuiLayer_UpdateInfection(PlayerGuiLayer __instance)
		{
			return !(SpectateCam.Instance?.Active ?? false);
		}

		[HarmonyPatch(typeof(GuiManager), "OnFocusStateChanged")]
		[HarmonyPostfix]
		private static void FocusStateChange(GuiManager __instance, eFocusState state)
		{
			SpectateCam? instance = SpectateCam.Instance;
			if (instance != null && instance.Active)
			{
				((RectTransformComp)GuiManager.PlayerLayer.Inventory).SetVisible(false);
			}
		}

		[HarmonyPatch(typeof(PlayerGuiLayer), "UpdateGUIElementsVisibility")]
		[HarmonyPostfix]
		private static void UpdateGUIElementsVisibility(GuiManager __instance, eFocusState currentState)
		{
			SpectateCam? instance = SpectateCam.Instance;
			if (instance != null && instance.Active)
			{
				((RectTransformComp)GuiManager.PlayerLayer.Inventory).SetVisible(false);
			}
		}

		[HarmonyPatch(typeof(PlayerGuiLayer), "ApplyMovementSway")]
		[HarmonyPrefix]
		private static void PlayerGuiLayer_ApplyMovementSway(PlayerGuiLayer __instance, ref Vector3 sway)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//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)
			PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
			if ((Object)(object)localPlayerAgent != (Object)null && (int)localPlayerAgent.Locomotion.m_currentStateEnum == 7)
			{
				sway = Vector3.zero;
			}
		}

		[HarmonyPatch(typeof(CM_PageMap), "OnEnable")]
		[HarmonyPostfix]
		private static void CM_PageMap_OnEnable(CM_PageMap __instance)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_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)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			SpectateCam? instance = SpectateCam.Instance;
			if (instance != null && instance.Active && CellSettingsManager.GetBoolValue((eCellSettingID)307))
			{
				AgentTarget? target = SpectateCam.Instance.Target;
				int num = (((object)target != null) ? target.SAgent.PlayerSlotIndex() : (-1));
				if (num != -1)
				{
					Vector3 position = ((Component)((Il2CppArrayBase<CM_MapPlayerGUIItem>)(object)__instance.m_syncedPlayers)[num]).transform.position;
					Vector3 val = __instance.m_mapHolder.transform.InverseTransformPoint(position);
					Transform transform = __instance.m_mapMover.transform;
					transform.localPosition -= val;
				}
			}
		}
	}
}
namespace Spectate.Patches.Compat
{
	[AttributeUsage(AttributeTargets.Method)]
	public class CompatPatchAttribute : Attribute
	{
		public HarmonyPatchType PatchType { get; }

		public string TypeName { get; }

		public string MethodName { get; }

		public CompatPatchAttribute(HarmonyPatchType patchType, string typeName, string methodName)
		{
			//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)
			PatchType = patchType;
			TypeName = typeName;
			MethodName = methodName;
		}
	}
	public static class CompatPatcher
	{
		public static void PatchAll(Harmony h)
		{
			Harmony h2 = h;
			CollectionExtensions.Do<Type>((IEnumerable<Type>)AccessTools.GetTypesFromAssembly(new StackTrace().GetFrame(1)?.GetMethod()?.ReflectedType?.Assembly), (Action<Type>)TryPatchTarget);
			void TryPatchTarget(Type encapsulator)
			{
				//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01dc: Invalid comparison between Unknown and I4
				//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ec: Invalid comparison between Unknown and I4
				//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fc: Invalid comparison between Unknown and I4
				//IL_0206: Unknown result type (might be due to invalid IL or missing references)
				//IL_020c: Invalid comparison between Unknown and I4
				//IL_0216: Unknown result type (might be due to invalid IL or missing references)
				//IL_021c: Invalid comparison between Unknown and I4
				//IL_023b: Unknown result type (might be due to invalid IL or missing references)
				//IL_024f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0263: 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_028b: Unknown result type (might be due to invalid IL or missing references)
				//IL_02af: Unknown result type (might be due to invalid IL or missing references)
				CompatTargetAttribute customAttribute = encapsulator.GetCustomAttribute<CompatTargetAttribute>();
				if (customAttribute != null)
				{
					if (((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey(customAttribute.TargetGuid))
					{
						foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(encapsulator))
						{
							CompatPatchAttribute customAttribute2 = declaredMethod.GetCustomAttribute<CompatPatchAttribute>();
							if (customAttribute2 != null)
							{
								Type type = AccessTools.TypeByName(customAttribute2.TypeName);
								if (type == null)
								{
									Logger.Error($"Failed to find type \"{customAttribute2.TypeName}\" for compat patch {declaredMethod.Name} in {encapsulator.FullName}!");
								}
								else
								{
									MethodInfo methodInfo = AccessTools.Method(type, customAttribute2.MethodName, (Type[])null, (Type[])null);
									if (methodInfo == null)
									{
										Logger.Error($"Failed to find method \"{customAttribute2.TypeName}\" => \"{customAttribute2.MethodName}\" for compat patch {declaredMethod.Name} in {encapsulator.FullName}!");
									}
									else
									{
										MethodInfo methodInfo2 = (((int)customAttribute2.PatchType == 1) ? declaredMethod : null);
										MethodInfo methodInfo3 = (((int)customAttribute2.PatchType == 2) ? declaredMethod : null);
										MethodInfo methodInfo4 = (((int)customAttribute2.PatchType == 3) ? declaredMethod : null);
										MethodInfo methodInfo5 = (((int)customAttribute2.PatchType == 4) ? declaredMethod : null);
										MethodInfo methodInfo6 = (((int)customAttribute2.PatchType == 6) ? declaredMethod : null);
										object obj = h2;
										obj = methodInfo;
										obj = (object)((!(methodInfo2 != null)) ? ((HarmonyMethod)null) : new HarmonyMethod(methodInfo2));
										obj = (object)((!(methodIn