Decompiled source of SpectatorPlus v1.1.0

Bepinex/plugins/SpectatorPlus/SpectatorPlus.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet.Object;
using HarmonyLib;
using Steamworks;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("SpectatorPlusRework")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SpectatorPlusRework")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("968984ed-bc83-4af7-8006-e4e46a9142ef")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SpectatorPlus;

[BepInPlugin("com.spectatorplus.mod", "SpectatorPlus", "1.1.0")]
[BepInProcess("MageArena.exe")]
public class SpectatorPlus : BaseUnityPlugin
{
	[HarmonyPatch(typeof(MainMenuManager), "ActuallyStartGameActually")]
	internal static class KillSpectatorOnGameStartPatch
	{
		private static void Postfix(MainMenuManager __instance)
		{
			ManualLogSource modLogger = ModLogger;
			if (modLogger != null)
			{
				modLogger.LogInfo((object)"ActuallyStartGameActually called - Game started, checking for spectator player");
			}
			if ((Object)(object)__instance.pm != (Object)null)
			{
				ManualLogSource modLogger2 = ModLogger;
				if (modLogger2 != null)
				{
					modLogger2.LogInfo((object)$"Found pm: {__instance.pm.playername}, IsOwner: {((NetworkBehaviour)__instance.pm).IsOwner}");
				}
				if (IsSpectatorPlayer(__instance.pm))
				{
					ManualLogSource modLogger3 = ModLogger;
					if (modLogger3 != null)
					{
						modLogger3.LogInfo((object)"Local player detected as spectator! Killing immediately");
					}
					((MonoBehaviour)__instance).StartCoroutine(KillSpectatorCoroutine(__instance.pm));
				}
				else
				{
					ManualLogSource modLogger4 = ModLogger;
					if (modLogger4 != null)
					{
						modLogger4.LogInfo((object)"Player is not spectator (not owner)");
					}
				}
			}
			else
			{
				ManualLogSource modLogger5 = ModLogger;
				if (modLogger5 != null)
				{
					modLogger5.LogWarning((object)"pm is null in ActuallyStartGameActually");
				}
			}
		}
	}

	[HarmonyPatch(typeof(PlayerRespawnManager), "RespawnRoutine")]
	internal static class DisableRespawnPatch
	{
		private static bool Prefix(PlayerRespawnManager __instance, ref IEnumerator __result)
		{
			ManualLogSource modLogger = ModLogger;
			if (modLogger != null)
			{
				modLogger.LogInfo((object)"RespawnRoutine called");
			}
			if (IsSpectatorPlayer(__instance.pmv))
			{
				ManualLogSource modLogger2 = ModLogger;
				if (modLogger2 != null)
				{
					modLogger2.LogInfo((object)"Replacing respawn routine with no-op for spectator player");
				}
				__result = NoOpCoroutine();
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(PlayerRespawnManager), "ColiRespawnRoutine")]
	internal static class DisableColiRespawnPatch
	{
		private static bool Prefix(PlayerRespawnManager __instance, ref IEnumerator __result)
		{
			ManualLogSource modLogger = ModLogger;
			if (modLogger != null)
			{
				modLogger.LogInfo((object)"ColiRespawnRoutine called");
			}
			if (IsSpectatorPlayer(__instance.pmv))
			{
				ManualLogSource modLogger2 = ModLogger;
				if (modLogger2 != null)
				{
					modLogger2.LogInfo((object)"Replacing coli respawn routine with no-op for spectator player");
				}
				__result = NoOpCoroutine();
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(PlayerRespawnManager), "SpectateRoutine")]
	internal static class CustomSpectateRoutinePatch
	{
		private static bool Prefix(PlayerRespawnManager __instance, ref IEnumerator __result)
		{
			ManualLogSource modLogger = ModLogger;
			if (modLogger != null)
			{
				modLogger.LogInfo((object)"SpectateRoutine called");
			}
			if (IsSpectatorPlayer(__instance.pmv))
			{
				ManualLogSource modLogger2 = ModLogger;
				if (modLogger2 != null)
				{
					modLogger2.LogInfo((object)"Starting custom spectate routine for spectator");
				}
				((MonoBehaviour)__instance).StartCoroutine(CustomSpectateCoroutine(__instance));
				__result = NoOpCoroutine();
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(SpawnWormHole), "TelePlayer", new Type[] { typeof(Collider) })]
	internal static class TelePlayerSpectatorPatch
	{
		private static bool Prefix(SpawnWormHole __instance, Collider other)
		{
			PlayerMovement val = default(PlayerMovement);
			if (!((Component)other).TryGetComponent<PlayerMovement>(ref val))
			{
				return true;
			}
			if (!IsSpectatorPlayer(val))
			{
				return true;
			}
			ManualLogSource modLogger = ModLogger;
			if (modLogger != null)
			{
				modLogger.LogInfo((object)"Host entered wormhole - starting spectate mode");
			}
			SetPlayerHealth(val, 0f);
			val.isDead = true;
			isSpectator = true;
			HideUIComponents();
			AccessTools.Field(typeof(SpawnWormHole), "tellied").SetValue(__instance, true);
			PlayerRespawnManager playerRespawnManager = GetPlayerRespawnManager(val);
			if ((Object)(object)playerRespawnManager != (Object)null)
			{
				((MonoBehaviour)playerRespawnManager).StartCoroutine(CustomSpectateCoroutine(playerRespawnManager));
			}
			return false;
		}
	}

	[HarmonyPatch(typeof(PlayerRespawnManager), "EndGame")]
	internal static class EndGamePatch
	{
		private static void Prefix()
		{
			try
			{
				ManualLogSource modLogger = ModLogger;
				if (modLogger != null)
				{
					modLogger.LogInfo((object)"Game ended - clearing all spectator states and resetting camera");
				}
				ResetAllStates();
			}
			catch (Exception ex)
			{
				ManualLogSource modLogger2 = ModLogger;
				if (modLogger2 != null)
				{
					modLogger2.LogError((object)("Error in EndGame patch: " + ex.Message));
				}
			}
		}
	}

	[CompilerGenerated]
	private sealed class <CustomSpectateCoroutine>d__59 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public PlayerRespawnManager manager;

		private GameObject[] <allPlayers>5__1;

		private PlayerMovement <firstAlivePlayer>5__2;

		private int <i>5__3;

		private PlayerMovement <pm>5__4;

		private int <i>5__5;

		private PlayerMovement <pm>5__6;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <CustomSpectateCoroutine>d__59(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<allPlayers>5__1 = null;
			<firstAlivePlayer>5__2 = null;
			<pm>5__4 = null;
			<pm>5__6 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if (isSpectateRoutineRunning)
				{
					return false;
				}
				isSpectateRoutineRunning = true;
				isSpectator = true;
				ModLogger.LogInfo((object)"Starting custom spectate routine");
				if ((Object)(object)manager == (Object)null)
				{
					ModLogger.LogError((object)"PlayerRespawnManager is null in CustomSpectateCoroutine");
					isSpectateRoutineRunning = false;
					return false;
				}
				<>2__current = (object)new WaitForSeconds(0.5f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<allPlayers>5__1 = GameObject.FindGameObjectsWithTag("Player");
				if (<allPlayers>5__1 == null)
				{
					ModLogger.LogWarning((object)"No players found for spectating (null array)");
					return false;
				}
				ModLogger.LogInfo((object)$"Found {<allPlayers>5__1.Length} total players");
				if (<allPlayers>5__1.Length == 0)
				{
					ModLogger.LogWarning((object)"No players found for spectating");
					return false;
				}
				<i>5__3 = 0;
				while (<i>5__3 < <allPlayers>5__1.Length)
				{
					if ((Object)(object)<allPlayers>5__1[<i>5__3] != (Object)null)
					{
						<pm>5__4 = <allPlayers>5__1[<i>5__3].GetComponent<PlayerMovement>();
						if ((Object)(object)<pm>5__4 != (Object)null)
						{
							ModLogger.LogInfo((object)$"Player {<i>5__3}: {<pm>5__4.playername}, IsOwner: {((NetworkBehaviour)<pm>5__4).IsOwner}, IsAlive: {IsPlayerAlive(<pm>5__4)}");
						}
						<pm>5__4 = null;
					}
					<i>5__3++;
				}
				<firstAlivePlayer>5__2 = null;
				<i>5__5 = 0;
				while (<i>5__5 < <allPlayers>5__1.Length)
				{
					if ((Object)(object)<allPlayers>5__1[<i>5__5] != (Object)null)
					{
						<pm>5__6 = <allPlayers>5__1[<i>5__5].GetComponent<PlayerMovement>();
						if ((Object)(object)<pm>5__6 != (Object)null && IsPlayerAlive(<pm>5__6) && !IsSpectatorPlayer(<pm>5__6))
						{
							<firstAlivePlayer>5__2 = <pm>5__6;
							currentPlayerIndex = <i>5__5;
							ModLogger.LogInfo((object)$"Selected player {<i>5__5}: {<pm>5__6.playername} for spectating");
							break;
						}
						<pm>5__6 = null;
					}
					<i>5__5++;
				}
				if ((Object)(object)<firstAlivePlayer>5__2 == (Object)null)
				{
					ModLogger.LogWarning((object)"No alive players found for spectating");
					isSpectateRoutineRunning = false;
					return false;
				}
				ModLogger.LogInfo((object)("Starting to spectate " + <firstAlivePlayer>5__2.playername));
				StartSpectating(<firstAlivePlayer>5__2);
				break;
			case 2:
				<>1__state = -1;
				UpdateSpectateCamera();
				if ((Object)(object)spectateTarget == (Object)null || !IsPlayerAlive(spectateTarget))
				{
					ModLogger.LogInfo((object)"Current spectate target is no longer valid, cycling to next player");
					CycleToNextPlayer();
				}
				break;
			}
			if (isSpectator)
			{
				<>2__current = null;
				<>1__state = 2;
				return true;
			}
			isSpectateRoutineRunning = false;
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	[CompilerGenerated]
	private sealed class <KillSpectatorCoroutine>d__58 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public PlayerMovement pm;

		private PlayerRespawnManager <prm>5__1;

		private Vector3 <currentPos>5__2;

		private Vector3 <newPos>5__3;

		private GameObject <netItemManager>5__4;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <KillSpectatorCoroutine>d__58(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<prm>5__1 = null;
			<netItemManager>5__4 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				ModLogger.LogInfo((object)"KillSpectatorCoroutine started");
				if ((Object)(object)pm == (Object)null)
				{
					ModLogger.LogError((object)"PlayerMovement is null in KillSpectatorCoroutine");
					return false;
				}
				<>2__current = (object)new WaitForSeconds(2f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				ModLogger.LogInfo((object)("Attempting to kill spectator player: " + pm?.playername));
				if ((Object)(object)pm != (Object)null && (Object)(object)((Component)pm).transform != (Object)null)
				{
					<currentPos>5__2 = ((Component)pm).transform.position;
					<newPos>5__3 = new Vector3(<currentPos>5__2.x, <currentPos>5__2.y - 100f, <currentPos>5__2.z);
					((Component)pm).transform.position = <newPos>5__3;
					ModLogger.LogInfo((object)$"Teleported player to {<newPos>5__3} (100 units below original position)");
				}
				if (IsPlayerAlive(pm))
				{
					ModLogger.LogInfo((object)"Player is alive, setting health to 0 and marking as dead");
					SetPlayerHealth(pm, 0f);
					pm.isDead = true;
					ModLogger.LogInfo((object)"Player killed - letting game systems handle death naturally");
				}
				else
				{
					ModLogger.LogInfo((object)"Player is already dead");
				}
				HideUIComponents();
				isSpectator = true;
				ModLogger.LogInfo((object)"Spectator marked and killed");
				<>2__current = (object)new WaitForSeconds(1f);
				<>1__state = 2;
				return true;
			case 2:
				<>1__state = -1;
				<prm>5__1 = GetPlayerRespawnManager(pm);
				if ((Object)(object)<prm>5__1 == (Object)null)
				{
					<netItemManager>5__4 = GameObject.FindGameObjectWithTag("NetItemManager");
					if ((Object)(object)<netItemManager>5__4 != (Object)null)
					{
						<prm>5__1 = <netItemManager>5__4.GetComponent<PlayerRespawnManager>();
					}
					<netItemManager>5__4 = null;
				}
				if ((Object)(object)<prm>5__1 != (Object)null)
				{
					ModLogger.LogInfo((object)"Manually starting custom spectate routine");
					((MonoBehaviour)<prm>5__1).StartCoroutine(CustomSpectateCoroutine(<prm>5__1));
				}
				else
				{
					ModLogger.LogError((object)"Could not find PlayerRespawnManager to start spectating!");
				}
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	[CompilerGenerated]
	private sealed class <NoOpCoroutine>d__53 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <NoOpCoroutine>d__53(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			if (<>1__state != 0)
			{
				return false;
			}
			<>1__state = -1;
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	internal static ManualLogSource ModLogger;

	private static Harmony harmony;

	private static bool isSpectator = false;

	private static bool isFreecamMode = false;

	private static bool isSpectateRoutineRunning = false;

	private static PlayerMovement spectateTarget = null;

	private static int currentPlayerIndex = 0;

	private static float spectateDistance = 5f;

	private static float minSpectateDistance = 2f;

	private static float maxSpectateDistance = 15f;

	private static float spectateHeight = 3f;

	private static bool invertMouseX = false;

	private static bool invertMouseY = false;

	private static float cameraSmoothing = 5f;

	private static Vector3 targetCameraPosition;

	private static Quaternion targetCameraRotation;

	private static Vector3 freecamPosition;

	private static float freecamYaw = 0f;

	private static float freecamPitch = 0f;

	private static float freecamSpeed = 10f;

	private static float freecamSensitivity = 2f;

	private static Vector3 originalCameraPosition;

	private static Quaternion originalCameraRotation;

	private static Transform originalCameraParent;

	private static GameObject cameraUIObject;

	private static ConfigEntry<bool> configInvertMouseX;

	private static ConfigEntry<bool> configInvertMouseY;

	private static ConfigEntry<float> configCameraSmoothing;

	private static ConfigEntry<float> configMouseSensitivity;

	private static ConfigEntry<float> configMinZoomDistance;

	private static ConfigEntry<float> configMaxZoomDistance;

	private static ConfigEntry<float> configDefaultZoomDistance;

	private static ConfigEntry<float> configZoomSpeed;

	private static ConfigEntry<float> configSpectateHeight;

	private static ConfigEntry<float> configFreecamSpeed;

	private static ConfigEntry<KeyCode> configFreecamToggleKey;

	private static ConfigEntry<KeyCode> configPlayerCycleKey;

	private void Awake()
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		ModLogger = Logger.CreateLogSource("SpectatorPlus");
		ModLogger.LogInfo((object)"SpectatorPlus mod loaded!");
		InitializeConfig();
		harmony = new Harmony("com.spectatorplus.mod");
		harmony.PatchAll(typeof(SpectatorPlus).Assembly);
		SceneManager.sceneLoaded += OnSceneLoaded;
		ModLogger.LogInfo((object)"Harmony patches applied!");
	}

	private void InitializeConfig()
	{
		configInvertMouseX = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "InvertMouseX", false, "Invert horizontal mouse movement");
		configInvertMouseY = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "InvertMouseY", false, "Invert vertical mouse movement");
		configCameraSmoothing = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraSmoothing", 8f, "Camera smoothing speed for spectating (higher = smoother)");
		configMouseSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "MouseSensitivity", 2f, "Mouse sensitivity");
		configMinZoomDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Spectating", "MinZoomDistance", 2f, "Minimum zoom distance when spectating");
		configMaxZoomDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Spectating", "MaxZoomDistance", 15f, "Maximum zoom distance when spectating");
		configDefaultZoomDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Spectating", "DefaultZoomDistance", 5f, "Default zoom distance when spectating");
		configZoomSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Spectating", "ZoomSpeed", 5f, "Zoom speed when using mouse wheel");
		configSpectateHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Spectating", "SpectateHeight", 3f, "Height offset when spectating players");
		configFreecamSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Freecam", "FreecamSpeed", 10f, "Movement speed in freecam mode");
		configFreecamToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "FreecamToggleKey", (KeyCode)286, "Key to toggle freecam mode on/off");
		configPlayerCycleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "PlayerCycleKey", (KeyCode)323, "Key to cycle between players when spectating");
		ApplyConfig();
		ValidateAndFixConfig();
		ModLogger.LogInfo((object)"BepInEx configuration initialized");
	}

	internal static void ApplyConfig()
	{
		invertMouseX = configInvertMouseX.Value;
		invertMouseY = configInvertMouseY.Value;
		cameraSmoothing = configCameraSmoothing.Value;
		freecamSensitivity = configMouseSensitivity.Value;
		minSpectateDistance = configMinZoomDistance.Value;
		maxSpectateDistance = configMaxZoomDistance.Value;
		spectateDistance = configDefaultZoomDistance.Value;
		spectateHeight = configSpectateHeight.Value;
		freecamSpeed = configFreecamSpeed.Value;
		ModLogger.LogInfo((object)$"Config applied - InvertX: {invertMouseX}, InvertY: {invertMouseY}, Smoothing: {cameraSmoothing}, Sensitivity: {freecamSensitivity}, FreecamSpeed: {freecamSpeed}");
	}

	internal static void ValidateAndFixConfig()
	{
		ModLogger.LogInfo((object)"Validating configuration values...");
		if (configCameraSmoothing.Value < 0.1f)
		{
			configCameraSmoothing.Value = 0.1f;
			ModLogger.LogWarning((object)"Camera smoothing was too low, set to minimum value 0.1");
		}
		if (configMouseSensitivity.Value < 0.1f)
		{
			configMouseSensitivity.Value = 0.1f;
			ModLogger.LogWarning((object)"Mouse sensitivity was too low, set to minimum value 0.1");
		}
		if (configMinZoomDistance.Value < 0.5f)
		{
			configMinZoomDistance.Value = 0.5f;
			ModLogger.LogWarning((object)"Min zoom distance was too low, set to minimum value 0.5");
		}
		if (configMaxZoomDistance.Value < configMinZoomDistance.Value)
		{
			configMaxZoomDistance.Value = configMinZoomDistance.Value + 5f;
			ModLogger.LogWarning((object)"Max zoom distance was lower than min, adjusted automatically");
		}
		if (configDefaultZoomDistance.Value < configMinZoomDistance.Value || configDefaultZoomDistance.Value > configMaxZoomDistance.Value)
		{
			configDefaultZoomDistance.Value = (configMinZoomDistance.Value + configMaxZoomDistance.Value) / 2f;
			ModLogger.LogWarning((object)"Default zoom distance was out of range, set to middle value");
		}
		if (configZoomSpeed.Value < 0.1f)
		{
			configZoomSpeed.Value = 0.1f;
			ModLogger.LogWarning((object)"Zoom speed was too low, set to minimum value 0.1");
		}
		if (configFreecamSpeed.Value < 0.1f)
		{
			configFreecamSpeed.Value = 0.1f;
			ModLogger.LogWarning((object)"Freecam speed was too low, set to minimum value 0.1");
		}
		ModLogger.LogInfo((object)"Configuration validation complete");
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		isSpectator = false;
		isFreecamMode = false;
		isSpectateRoutineRunning = false;
		spectateTarget = null;
		currentPlayerIndex = 0;
		cameraUIObject = null;
		ManualLogSource modLogger = ModLogger;
		if (modLogger != null)
		{
			modLogger.LogInfo((object)("Scene loaded (" + ((Scene)(ref scene)).name + ") - spectator state cleared"));
		}
	}

	private void Update()
	{
		//IL_0023: 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)
		if (IsCurrentPlayerHost() && isSpectator)
		{
			if (Input.GetKeyDown(configFreecamToggleKey.Value))
			{
				ToggleFreecam();
			}
			if (isFreecamMode)
			{
				UpdateFreecam();
			}
			if (Input.GetKeyDown(configPlayerCycleKey.Value) && !isFreecamMode)
			{
				CycleToNextPlayer();
			}
		}
	}

	internal static bool IsPlayerAlive(PlayerMovement pm)
	{
		if ((Object)(object)pm == (Object)null)
		{
			return false;
		}
		if (pm.isDead)
		{
			return false;
		}
		if (pm.playerHealth <= 0f)
		{
			return false;
		}
		return true;
	}

	internal static void SetPlayerHealth(PlayerMovement pm, float health)
	{
		if (!((Object)(object)pm == (Object)null))
		{
			pm.playerHealth = health;
		}
	}

	internal static PlayerRespawnManager GetPlayerRespawnManager(PlayerMovement pm)
	{
		return PlayerRespawnManager.instance;
	}

	[IteratorStateMachine(typeof(<NoOpCoroutine>d__53))]
	internal static IEnumerator NoOpCoroutine()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <NoOpCoroutine>d__53(0);
	}

	internal static bool IsSpectatorPlayer(PlayerMovement pm)
	{
		if ((Object)(object)pm == (Object)null)
		{
			return false;
		}
		if (!IsCurrentPlayerHost())
		{
			return false;
		}
		return ((NetworkBehaviour)pm).IsOwner;
	}

	internal static bool IsCurrentPlayerHost()
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: 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_005f: 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_0079: 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)
		try
		{
			if ((Object)(object)BootstrapManager.instance == (Object)null)
			{
				return false;
			}
			if (BootstrapManager.instance.CurrentLobbyID == 0)
			{
				return false;
			}
			CSteamID val = default(CSteamID);
			((CSteamID)(ref val))..ctor(BootstrapManager.instance.CurrentLobbyID);
			CSteamID lobbyOwner = SteamMatchmaking.GetLobbyOwner(val);
			CSteamID steamID = SteamUser.GetSteamID();
			if (lobbyOwner == CSteamID.Nil || steamID == CSteamID.Nil)
			{
				return false;
			}
			return lobbyOwner == steamID;
		}
		catch (Exception ex)
		{
			ManualLogSource modLogger = ModLogger;
			if (modLogger != null)
			{
				modLogger.LogError((object)("Error checking host status: " + ex.Message));
			}
			return false;
		}
	}

	internal static void HideUIComponents()
	{
		//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)
		if (!IsCurrentPlayerHost())
		{
			return;
		}
		ModLogger.LogInfo((object)"Hiding UI components for spectator mode");
		Camera main = Camera.main;
		if ((Object)(object)main != (Object)null)
		{
			Transform val = ((Component)main).transform.Find("ui");
			if ((Object)(object)val != (Object)null)
			{
				cameraUIObject = ((Component)val).gameObject;
				cameraUIObject.SetActive(false);
				ModLogger.LogInfo((object)"Hidden Main Camera/UI");
			}
			else
			{
				ModLogger.LogWarning((object)"Main Camera/UI not found");
			}
		}
		if (SceneManager.sceneCount == 0)
		{
			ModLogger.LogWarning((object)"No scenes loaded, cannot hide UI components");
			return;
		}
		Scene sceneByName = SceneManager.GetSceneByName("GameScene");
		if (((Scene)(ref sceneByName)).isLoaded)
		{
			ModLogger.LogInfo((object)"Found GameScene, hiding inventory and level up UI");
			GameObject[] rootGameObjects = ((Scene)(ref sceneByName)).GetRootGameObjects();
			if (rootGameObjects == null)
			{
				return;
			}
			GameObject[] array = rootGameObjects;
			foreach (GameObject val2 in array)
			{
				if ((Object)(object)val2 != (Object)null && ((Object)val2).name == "Canvas")
				{
					Transform val3 = val2.transform.Find("INVUI");
					if ((Object)(object)val3 != (Object)null)
					{
						((Component)val3).gameObject.SetActive(false);
						ModLogger.LogInfo((object)"Hidden Canvas/INVUI");
					}
					Transform val4 = val2.transform.Find("lvluptext");
					if ((Object)(object)val4 != (Object)null)
					{
						((Component)val4).gameObject.SetActive(false);
						ModLogger.LogInfo((object)"Hidden Canvas/lvluptext");
					}
					break;
				}
			}
		}
		else
		{
			ModLogger.LogWarning((object)"GameScene not found or not loaded");
		}
	}

	internal static void RestoreUIComponents()
	{
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		if (!IsCurrentPlayerHost())
		{
			return;
		}
		ModLogger.LogInfo((object)"Restoring UI components");
		if ((Object)(object)cameraUIObject != (Object)null)
		{
			cameraUIObject.SetActive(true);
			ModLogger.LogInfo((object)"Restored Main Camera/UI");
			cameraUIObject = null;
		}
		if (SceneManager.sceneCount == 0)
		{
			ModLogger.LogWarning((object)"No scenes loaded, cannot restore UI components");
			return;
		}
		Scene sceneByName = SceneManager.GetSceneByName("GameScene");
		if (!((Scene)(ref sceneByName)).isLoaded)
		{
			return;
		}
		GameObject[] rootGameObjects = ((Scene)(ref sceneByName)).GetRootGameObjects();
		if (rootGameObjects == null)
		{
			return;
		}
		GameObject[] array = rootGameObjects;
		foreach (GameObject val in array)
		{
			if ((Object)(object)val != (Object)null && ((Object)val).name == "Canvas")
			{
				Transform val2 = val.transform.Find("INVUI");
				if ((Object)(object)val2 != (Object)null)
				{
					((Component)val2).gameObject.SetActive(true);
					ModLogger.LogInfo((object)"Restored Canvas/INVUI");
				}
				Transform val3 = val.transform.Find("lvluptext");
				if ((Object)(object)val3 != (Object)null)
				{
					((Component)val3).gameObject.SetActive(true);
					ModLogger.LogInfo((object)"Restored Canvas/lvluptext");
				}
				break;
			}
		}
	}

	[IteratorStateMachine(typeof(<KillSpectatorCoroutine>d__58))]
	internal static IEnumerator KillSpectatorCoroutine(PlayerMovement pm)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <KillSpectatorCoroutine>d__58(0)
		{
			pm = pm
		};
	}

	[IteratorStateMachine(typeof(<CustomSpectateCoroutine>d__59))]
	internal static IEnumerator CustomSpectateCoroutine(PlayerRespawnManager manager)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <CustomSpectateCoroutine>d__59(0)
		{
			manager = manager
		};
	}

	internal static void StartSpectating(PlayerMovement targetPlayer)
	{
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)targetPlayer == (Object)null)
		{
			ModLogger.LogError((object)"Target player is null in StartSpectating");
			return;
		}
		if ((Object)(object)((Component)targetPlayer).transform == (Object)null)
		{
			ModLogger.LogError((object)"Target player transform is null in StartSpectating");
			return;
		}
		ModLogger.LogInfo((object)("Starting to spectate " + targetPlayer.playername));
		Camera main = Camera.main;
		if ((Object)(object)main != (Object)null && (Object)(object)spectateTarget == (Object)null)
		{
			ModLogger.LogInfo((object)("Main camera found: " + ((Object)main).name));
			originalCameraPosition = ((Component)main).transform.position;
			originalCameraRotation = ((Component)main).transform.rotation;
			originalCameraParent = ((Component)main).transform.parent;
			ManualLogSource modLogger = ModLogger;
			object arg = originalCameraPosition;
			object arg2 = originalCameraRotation;
			Transform obj = originalCameraParent;
			modLogger.LogInfo((object)string.Format("Stored original camera state - Pos: {0}, Rot: {1}, Parent: {2}", arg, arg2, ((obj != null) ? ((Object)obj).name : null) ?? "None"));
			((Component)main).transform.SetParent((Transform)null);
			freecamYaw = 0f;
			freecamPitch = 0f;
		}
		else if ((Object)(object)main == (Object)null)
		{
			ModLogger.LogError((object)"Main camera not found!");
			return;
		}
		spectateTarget = targetPlayer;
		ModLogger.LogInfo((object)("Set spectate target to " + targetPlayer.playername));
		if (isFreecamMode)
		{
			ModLogger.LogInfo((object)"Disabling freecam before starting spectating");
			DisableFreecam();
		}
		freecamYaw = 0f;
		freecamPitch = 0f;
		spectateDistance = configDefaultZoomDistance.Value;
		ModLogger.LogInfo((object)("Reset camera angles and zoom for " + targetPlayer.playername));
	}

	internal static void ReloadConfig()
	{
		ModLogger.LogInfo((object)"Reloading configuration...");
		ApplyConfig();
		ModLogger.LogInfo((object)"Configuration reloaded successfully");
	}

	internal static void UpdateSpectateCamera()
	{
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: 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_0204: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_0283: Unknown result type (might be due to invalid IL or missing references)
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)spectateTarget == (Object)null || isFreecamMode)
		{
			return;
		}
		if ((Object)(object)((Component)spectateTarget).transform == (Object)null)
		{
			ModLogger.LogWarning((object)"Spectate target transform is null, cannot update camera");
			return;
		}
		Camera main = Camera.main;
		if (!((Object)(object)main == (Object)null))
		{
			Transform val = spectateTarget.SpectatePoint;
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)spectateTarget).transform;
			}
			float num = Input.GetAxis("Mouse X") * freecamSensitivity;
			float num2 = Input.GetAxis("Mouse Y") * freecamSensitivity;
			if (invertMouseX)
			{
				num = 0f - num;
			}
			if (invertMouseY)
			{
				num2 = 0f - num2;
			}
			float axis = Input.GetAxis("Mouse ScrollWheel");
			if (axis != 0f)
			{
				spectateDistance -= axis * configZoomSpeed.Value;
				spectateDistance = Mathf.Clamp(spectateDistance, minSpectateDistance, maxSpectateDistance);
			}
			freecamYaw += num;
			freecamPitch -= num2 / 2f;
			freecamPitch = Mathf.Clamp(freecamPitch, -60f, 60f);
			float num3 = freecamYaw * ((float)Math.PI / 180f);
			float num4 = freecamPitch * ((float)Math.PI / 180f);
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(Mathf.Cos(num3) * spectateDistance, 0f, Mathf.Sin(num3) * spectateDistance);
			float num5 = spectateHeight + Mathf.Sin(num4) * spectateDistance;
			float num6 = Mathf.Cos(num4);
			val2 *= num6;
			targetCameraPosition = val.position + Vector3.up * num5 + val2;
			Vector3 val3 = val.position + Vector3.up * 1.5f;
			targetCameraRotation = Quaternion.LookRotation(val3 - targetCameraPosition);
			if (cameraSmoothing > 0f)
			{
				((Component)main).transform.position = Vector3.Lerp(((Component)main).transform.position, targetCameraPosition, Time.deltaTime * cameraSmoothing);
				((Component)main).transform.rotation = Quaternion.Lerp(((Component)main).transform.rotation, targetCameraRotation, Time.deltaTime * cameraSmoothing);
			}
			else
			{
				((Component)main).transform.position = targetCameraPosition;
				((Component)main).transform.rotation = targetCameraRotation;
			}
		}
	}

	internal static void StopSpectating()
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		ModLogger.LogInfo((object)"Stopping spectating");
		Camera main = Camera.main;
		if ((Object)(object)main != (Object)null)
		{
			if ((Object)(object)((Component)main).transform == (Object)null)
			{
				ModLogger.LogError((object)"Main camera transform is null when stopping spectating");
				return;
			}
			((Component)main).transform.position = originalCameraPosition;
			((Component)main).transform.rotation = originalCameraRotation;
			if ((Object)(object)originalCameraParent != (Object)null)
			{
				((Component)main).transform.SetParent(originalCameraParent);
			}
		}
		spectateTarget = null;
		isSpectator = false;
	}

	internal static void CycleToNextPlayer()
	{
		GameObject[] array = GameObject.FindGameObjectsWithTag("Player");
		if (array == null || array.Length == 0)
		{
			return;
		}
		int num = 0;
		do
		{
			currentPlayerIndex = (currentPlayerIndex + 1) % array.Length;
			if ((Object)(object)array[currentPlayerIndex] != (Object)null)
			{
				PlayerMovement component = array[currentPlayerIndex].GetComponent<PlayerMovement>();
				if ((Object)(object)component != (Object)null && IsPlayerAlive(component) && !IsSpectatorPlayer(component))
				{
					StartSpectating(component);
					return;
				}
			}
			num++;
		}
		while (num < array.Length);
		ModLogger.LogWarning((object)"No alive players found to spectate");
	}

	internal static void ResetAllStates()
	{
		if (IsCurrentPlayerHost())
		{
			ModLogger.LogInfo((object)"Resetting all spectator and freecam states...");
			StopSpectating();
			DisableFreecam();
			RestoreUIComponents();
			isSpectator = false;
			isFreecamMode = false;
			isSpectateRoutineRunning = false;
			spectateTarget = null;
			currentPlayerIndex = 0;
			ModLogger.LogInfo((object)"All states reset.");
		}
	}

	internal static void ToggleFreecam()
	{
		if (isFreecamMode)
		{
			DisableFreecam();
		}
		else
		{
			EnableFreecam();
		}
	}

	internal static void EnableFreecam()
	{
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
		if (!isFreecamMode)
		{
			ModLogger.LogInfo((object)"Enabling freecam mode");
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				ModLogger.LogError((object)"Could not find main camera for freecam");
				return;
			}
			if ((Object)(object)((Component)main).transform == (Object)null)
			{
				ModLogger.LogError((object)"Main camera transform is null for freecam");
				return;
			}
			freecamPosition = ((Component)main).transform.position;
			freecamYaw = ((Component)main).transform.eulerAngles.y;
			freecamPitch = ((Component)main).transform.eulerAngles.x;
			((Component)main).transform.SetParent((Transform)null);
			isFreecamMode = true;
			ModLogger.LogInfo((object)$"Freecam enabled at position {freecamPosition}");
		}
	}

	internal static void DisableFreecam()
	{
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		if (!isFreecamMode)
		{
			return;
		}
		ModLogger.LogInfo((object)"Disabling freecam mode");
		Camera main = Camera.main;
		if ((Object)(object)main != (Object)null)
		{
			if ((Object)(object)((Component)main).transform == (Object)null)
			{
				ModLogger.LogError((object)"Main camera transform is null when disabling freecam");
				return;
			}
			if ((Object)(object)spectateTarget != (Object)null)
			{
				UpdateSpectateCamera();
			}
			else
			{
				((Component)main).transform.position = originalCameraPosition;
				((Component)main).transform.rotation = originalCameraRotation;
				if ((Object)(object)originalCameraParent != (Object)null)
				{
					((Component)main).transform.SetParent(originalCameraParent);
				}
			}
		}
		isFreecamMode = false;
		ModLogger.LogInfo((object)"Freecam disabled");
	}

	internal static void UpdateFreecam()
	{
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: 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_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		if (!isFreecamMode)
		{
			return;
		}
		Camera main = Camera.main;
		if ((Object)(object)main == (Object)null)
		{
			return;
		}
		if ((Object)(object)((Component)main).transform == (Object)null)
		{
			ModLogger.LogError((object)"Main camera transform is null in UpdateFreecam");
			return;
		}
		float num = Input.GetAxis("Mouse X") * freecamSensitivity;
		float num2 = Input.GetAxis("Mouse Y") * freecamSensitivity;
		freecamYaw += num;
		freecamPitch -= num2;
		freecamPitch = Mathf.Clamp(freecamPitch, -80f, 80f);
		float num3 = freecamSpeed;
		if (Input.GetKey((KeyCode)304))
		{
			num3 *= 2.5f;
		}
		if (Input.GetKey((KeyCode)306))
		{
			num3 *= 0.5f;
		}
		Vector3 val = Vector3.zero;
		if (Input.GetKey((KeyCode)119))
		{
			val += Vector3.forward;
		}
		if (Input.GetKey((KeyCode)115))
		{
			val += Vector3.back;
		}
		if (Input.GetKey((KeyCode)97))
		{
			val += Vector3.left;
		}
		if (Input.GetKey((KeyCode)100))
		{
			val += Vector3.right;
		}
		if (Input.GetKey((KeyCode)32))
		{
			val += Vector3.up;
		}
		if (Input.GetKey((KeyCode)308))
		{
			val += Vector3.down;
		}
		if (((Vector3)(ref val)).magnitude > 0f)
		{
			val = ((Component)main).transform.TransformDirection(((Vector3)(ref val)).normalized);
			freecamPosition += val * num3 * Time.deltaTime;
		}
		((Component)main).transform.position = freecamPosition;
		((Component)main).transform.rotation = Quaternion.Euler(freecamPitch, freecamYaw, 0f);
	}
}