using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using MelonLoader;
using MelonLoader.Preferences;
using SpectatorMod;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(SpectatorModMain), "Spectator Cam", "2.4.0", "Int_Void", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("SpectatorMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SpectatorMod")]
[assembly: AssemblyTitle("SpectatorMod")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SpectatorMod;
public class SpectatorModMain : MelonMod
{
public enum ControllerSide
{
Left,
Right,
Both
}
private class TrackedPlayer
{
public Transform HeadBone;
public string Name;
}
public static MelonPreferences_Category PrefCategory;
public static MelonPreferences_Entry<ControllerSide> PrefController;
public static MelonPreferences_Entry<bool> PrefIsEnabled;
private bool _isSpectating = false;
private Camera _specCamera;
private float _buttonPressTime = -1f;
private const float MAX_HOLD_TIME = 0.4f;
private bool _isButtonHeld = false;
private List<TrackedPlayer> _players = new List<TrackedPlayer>();
private int _currentPlayerIndex = 0;
private TrackedPlayer _currentPlayer;
private Vector3 _cameraOffset = new Vector3(0f, 0.12f, 0.05f);
public override void OnInitializeMelon()
{
((MelonBase)this).LoggerInstance.Msg("Spectator Mod v2.4 Initialized!");
Hooking.OnLevelLoaded += OnLevelLoaded;
SetupPreferences();
SetupBoneMenu();
}
private void SetupPreferences()
{
PrefCategory = MelonPreferences.CreateCategory("SpectatorMod", "Spectator Mod");
PrefIsEnabled = PrefCategory.CreateEntry<bool>("IsEnabled", true, "Enable Mod", (string)null, false, false, (ValueValidator)null, (string)null);
PrefController = PrefCategory.CreateEntry<ControllerSide>("ControllerSide", ControllerSide.Left, "Controller Side", (string)null, false, false, (ValueValidator)null, (string)null);
}
private void SetupBoneMenu()
{
//IL_000b: 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)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
Page val = Page.Root.CreatePage("Spectator Mod", Color.white, 0, true);
val.CreateBool("Mod Enabled", Color.green, PrefIsEnabled.Value, (Action<bool>)delegate(bool flag)
{
PrefIsEnabled.Value = flag;
PrefCategory.SaveToFile(false);
if (!flag && _isSpectating)
{
StopSpectating();
}
});
val.CreateEnum("Controller Side", Color.white, (Enum)PrefController.Value, (Action<Enum>)delegate(Enum obj)
{
PrefController.Value = (ControllerSide)(object)obj;
PrefCategory.SaveToFile(false);
});
}
private void OnLevelLoaded(LevelInfo info)
{
StopSpectating();
}
public override void OnUpdate()
{
//IL_0191: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: 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)
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
if (!PrefIsEnabled.Value || (Object)(object)Player.RigManager == (Object)null)
{
return;
}
bool flag = false;
bool flag2 = false;
bool flag3 = false;
try
{
BaseController leftController = Player.LeftController;
BaseController rightController = Player.RightController;
bool flag4 = PrefController.Value == ControllerSide.Left || PrefController.Value == ControllerSide.Both;
bool flag5 = PrefController.Value == ControllerSide.Right || PrefController.Value == ControllerSide.Both;
bool flag6 = flag4 && (Object)(object)leftController != (Object)null && leftController.GetBButtonDown();
bool flag7 = flag5 && (Object)(object)rightController != (Object)null && rightController.GetBButtonDown();
bool flag8 = flag4 && (Object)(object)leftController != (Object)null && leftController.GetBButton();
bool flag9 = flag5 && (Object)(object)rightController != (Object)null && rightController.GetBButton();
bool flag10 = flag8 || flag9;
if ((flag6 || flag7) && !_isButtonHeld)
{
_buttonPressTime = Time.time;
_isButtonHeld = true;
}
else if (!flag10 && _isButtonHeld)
{
_isButtonHeld = false;
float num = Time.time - _buttonPressTime;
if (num <= 0.4f && _buttonPressTime > 0f)
{
flag2 = true;
}
_buttonPressTime = -1f;
}
Vector2 thumbStickAxis;
if (flag4 && (Object)(object)leftController != (Object)null)
{
bool num2 = flag3;
thumbStickAxis = leftController.GetThumbStickAxis();
flag3 = num2 | (((Vector2)(ref thumbStickAxis)).magnitude > 0.2f);
}
if (flag5 && (Object)(object)rightController != (Object)null)
{
bool num3 = flag3;
thumbStickAxis = rightController.GetThumbStickAxis();
flag3 = num3 | (((Vector2)(ref thumbStickAxis)).magnitude > 0.2f);
}
}
catch
{
}
if (Input.GetKeyDown((KeyCode)107))
{
flag2 = true;
}
if (Input.GetKey((KeyCode)119) || Input.GetKey((KeyCode)97) || Input.GetKey((KeyCode)115) || Input.GetKey((KeyCode)100))
{
flag3 = true;
}
if (flag2)
{
if (!_isSpectating)
{
StartSpectating();
}
else
{
CycleTarget();
}
}
if (_isSpectating)
{
if (flag3)
{
StopSpectating();
}
else
{
UpdateCameraPosition();
}
}
}
private void StartSpectating()
{
RefreshPlayers();
if (_players.Count != 0)
{
_isSpectating = true;
_currentPlayerIndex = 0;
SetupCamera();
AttachToCurrentPlayer();
}
}
private void StopSpectating()
{
_isSpectating = false;
_currentPlayer = null;
if ((Object)(object)_specCamera != (Object)null)
{
Object.Destroy((Object)(object)((Component)_specCamera).gameObject);
_specCamera = null;
}
}
private void CycleTarget()
{
RefreshPlayers();
if (_players.Count == 0)
{
StopSpectating();
return;
}
_currentPlayerIndex++;
if (_currentPlayerIndex >= _players.Count)
{
_currentPlayerIndex = 0;
}
AttachToCurrentPlayer();
}
private void RefreshPlayers()
{
_players.Clear();
RigManager rigManager = Player.RigManager;
object obj;
if (rigManager == null)
{
obj = null;
}
else
{
PhysicsRig physicsRig = rigManager.physicsRig;
obj = ((physicsRig != null) ? ((Rig)physicsRig).m_head : null);
}
if ((Object)obj != (Object)null)
{
_players.Add(new TrackedPlayer
{
HeadBone = ((Rig)Player.RigManager.physicsRig).m_head,
Name = "LOCAL PLAYER"
});
}
Il2CppArrayBase<RigManager> val = Object.FindObjectsOfType<RigManager>();
foreach (RigManager item in val)
{
if ((Object)(object)item != (Object)(object)Player.RigManager)
{
PhysicsRig physicsRig2 = item.physicsRig;
if ((Object)(object)((physicsRig2 != null) ? ((Rig)physicsRig2).m_head : null) != (Object)null)
{
_players.Add(new TrackedPlayer
{
HeadBone = ((Rig)item.physicsRig).m_head,
Name = "FUSION PLAYER"
});
}
}
}
}
private void SetupCamera()
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
if (!((Object)(object)_specCamera != (Object)null))
{
GameObject val = new GameObject("SpectatorCamera_VR");
_specCamera = val.AddComponent<Camera>();
if ((Object)(object)Camera.main != (Object)null)
{
_specCamera.CopyFrom(Camera.main);
}
else
{
_specCamera.fieldOfView = 90f;
}
_specCamera.nearClipPlane = 0.15f;
_specCamera.targetTexture = null;
_specCamera.depth = 100f;
((Behaviour)_specCamera).enabled = true;
}
}
private void AttachToCurrentPlayer()
{
if (_players.Count != 0 && _currentPlayerIndex < _players.Count)
{
_currentPlayer = _players[_currentPlayerIndex];
}
}
private void UpdateCameraPosition()
{
//IL_0045: 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_005b: 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_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_currentPlayer?.HeadBone == (Object)null || (Object)(object)_specCamera == (Object)null)
{
StopSpectating();
return;
}
Transform headBone = _currentPlayer.HeadBone;
Vector3 val = headBone.up * _cameraOffset.y + headBone.forward * _cameraOffset.z;
((Component)_specCamera).transform.position = headBone.position + val;
((Component)_specCamera).transform.rotation = headBone.rotation;
}
public override void OnGUI()
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: 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_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Expected O, but got Unknown
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: 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_0086: Expected O, but got Unknown
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
if (PrefIsEnabled.Value && _isSpectating && _currentPlayer != null)
{
GUIStyle val = new GUIStyle(GUI.skin.label)
{
fontSize = 30,
fontStyle = (FontStyle)1
};
val.normal.textColor = Color.cyan;
GUIStyle val2 = val;
GUIStyle val3 = new GUIStyle(GUI.skin.label)
{
fontSize = 20
};
val3.normal.textColor = Color.white;
GUIStyle val4 = val3;
GUI.Label(new Rect(20f, 20f, 800f, 50f), "SPECTATING: " + _currentPlayer.Name, val2);
GUI.Label(new Rect(20f, 55f, 600f, 30f), "Tap Y/B (<0.4s) to cycle | Stick to exit", val4);
}
}
}