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 System.Security;
using System.Security.Permissions;
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("SpectatorPlus")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SpectatorPlus")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("98cf1544-b8e1-4464-a01a-376394e5ef86")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace SpectatorPlus
{
[BepInPlugin("com.spectatorplus.mod", "SpectatorPlus", "1.0.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)
{
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));
return false;
}
return true;
}
}
[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__55 : 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__55(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_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
ModLogger.LogInfo((object)"Starting custom spectate routine");
if ((Object)(object)manager == (Object)null)
{
ModLogger.LogError((object)"PlayerRespawnManager is null in CustomSpectateCoroutine");
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");
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;
}
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__54 : 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__54(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__49 : 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__49(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 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 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);
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()
{
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
}
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)
{
if ((Object)(object)pm == (Object)null)
{
return null;
}
return pm.prm;
}
[IteratorStateMachine(typeof(<NoOpCoroutine>d__49))]
internal static IEnumerator NoOpCoroutine()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <NoOpCoroutine>d__49(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_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)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: 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_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)BootstrapManager.instance == (Object)null)
{
return false;
}
if (BootstrapManager.CurrentLobbyID == 0)
{
return false;
}
CSteamID val = default(CSteamID);
((CSteamID)(ref val))..ctor(BootstrapManager.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_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)
if (!IsCurrentPlayerHost())
{
return;
}
ModLogger.LogInfo((object)"Hiding UI components for spectator mode");
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 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(false);
ModLogger.LogInfo((object)"Hidden Canvas/INVUI");
}
Transform val3 = val.transform.Find("lvluptext");
if ((Object)(object)val3 != (Object)null)
{
((Component)val3).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_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)
if (!IsCurrentPlayerHost())
{
return;
}
ModLogger.LogInfo((object)"Restoring UI components");
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__54))]
internal static IEnumerator KillSpectatorCoroutine(PlayerMovement pm)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <KillSpectatorCoroutine>d__54(0)
{
pm = pm
};
}
[IteratorStateMachine(typeof(<CustomSpectateCoroutine>d__55))]
internal static IEnumerator CustomSpectateCoroutine(PlayerRespawnManager manager)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <CustomSpectateCoroutine>d__55(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;
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);
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}