using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BoneLib;
using BoneLib.BoneMenu;
using CustomFov;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Main), "CustomFov", "1.0.0", "kamonkus", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace CustomFov
{
internal static class FovController
{
private static Camera _cam;
private static float _gameFov = 90f;
private static float _lastSet = -1f;
private static float _nextSearch;
private static float _nextProjCheck;
private static bool _warnedNoCam;
private static bool _projNoted;
private static readonly string[] Keywords = new string[6] { "spectator", "mirror", "monitor", "desktop", "flat", "display" };
public static void OnLevelLoaded()
{
_cam = null;
_nextSearch = 0f;
}
private static List<Camera> Candidates()
{
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
List<Camera> list = new List<Camera>();
Il2CppReferenceArray<Camera> allCameras = Camera.allCameras;
for (int i = 0; i < ((Il2CppArrayBase<Camera>)(object)allCameras).Length; i++)
{
Camera val = ((Il2CppArrayBase<Camera>)(object)allCameras)[i];
if (!((Object)(object)val == (Object)null) && ((Behaviour)val).enabled && ((Component)val).gameObject.activeInHierarchy && !((Object)(object)val.targetTexture != (Object)null) && (int)val.stereoTargetEye == 0)
{
list.Add(val);
}
}
return list;
}
private static Camera PickCamera()
{
List<Camera> list = Candidates();
if (list.Count == 0)
{
return null;
}
foreach (Camera item in list)
{
string text = ((Object)item).name.ToLowerInvariant();
string[] keywords = Keywords;
foreach (string value in keywords)
{
if (text.Contains(value))
{
return item;
}
}
}
Camera val = list[0];
foreach (Camera item2 in list)
{
if (item2.depth > val.depth)
{
val = item2;
}
}
return val;
}
private static void LogCameras()
{
//IL_009a: 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)
try
{
Il2CppReferenceArray<Camera> allCameras = Camera.allCameras;
for (int i = 0; i < ((Il2CppArrayBase<Camera>)(object)allCameras).Length; i++)
{
Camera val = ((Il2CppArrayBase<Camera>)(object)allCameras)[i];
if (!((Object)(object)val == (Object)null))
{
MelonLogger.Msg("[CustomFov] camera: " + ((Object)val).name + " fov=" + val.fieldOfView.ToString("0.#") + " aspect=" + val.aspect.ToString("0.##") + " depth=" + val.depth + " stereo=" + ((object)val.stereoTargetEye/*cast due to .constrained prefix*/).ToString() + " texture=" + ((Object)(object)val.targetTexture != (Object)null) + " display=" + val.targetDisplay);
}
}
}
catch (Exception ex)
{
MelonLogger.Warning("[CustomFov] could not list cameras: " + ex.Message);
}
}
public static void Tick()
{
//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
float unscaledTime = Time.unscaledTime;
if ((Object)(object)_cam == (Object)null || !((Behaviour)_cam).enabled || !((Component)_cam).gameObject.activeInHierarchy)
{
_cam = null;
_lastSet = -1f;
if (unscaledTime < _nextSearch)
{
return;
}
_nextSearch = unscaledTime + 1f;
_cam = PickCamera();
if ((Object)(object)_cam == (Object)null)
{
if (!_warnedNoCam)
{
_warnedNoCam = true;
MelonLogger.Warning("[CustomFov] no monitor camera found yet.");
LogCameras();
}
return;
}
_warnedNoCam = false;
_gameFov = _cam.fieldOfView;
MelonLogger.Msg("[CustomFov] using camera: " + ((Object)_cam).name + " (game FOV " + _gameFov.ToString("0.#") + ")");
if (!Settings.Override.Value)
{
Settings.ShowFov(_gameFov);
}
}
float fieldOfView = _cam.fieldOfView;
if (_lastSet < 0f || !Mathf.Approximately(fieldOfView, _lastSet))
{
_gameFov = fieldOfView;
}
if (!Settings.Override.Value)
{
if (_lastSet >= 0f)
{
_cam.fieldOfView = _gameFov;
_cam.ResetProjectionMatrix();
_lastSet = -1f;
}
return;
}
float num = Mathf.Clamp(Settings.Fov.Value, 10f, 170f);
if (!Mathf.Approximately(fieldOfView, num))
{
_cam.fieldOfView = num;
}
_lastSet = num;
if (!(unscaledTime >= _nextProjCheck))
{
return;
}
_nextProjCheck = unscaledTime + 0.5f;
float m = _cam.projectionMatrix.m11;
if (Mathf.Abs(m) > 0.0001f && Mathf.Abs(2f * Mathf.Atan(1f / m) * 57.29578f - num) > 1f)
{
_cam.ResetProjectionMatrix();
if (!_projNoted)
{
_projNoted = true;
MelonLogger.Msg("[CustomFov] camera had a custom projection, it was reset to use the FOV.");
}
}
}
public static void ResetToGame()
{
Settings.Override.Value = false;
Settings.Dirty();
if ((Object)(object)_cam != (Object)null)
{
_cam.fieldOfView = _gameFov;
_cam.ResetProjectionMatrix();
_lastSet = -1f;
Settings.ShowFov(_gameFov);
}
}
}
public class Main : MelonMod
{
private float _nextErrorLog;
public override void OnInitializeMelon()
{
Settings.Init();
Hooking.OnLevelLoaded += delegate
{
FovController.OnLevelLoaded();
};
Settings.BuildMenu();
MelonLogger.Msg("CustomFov loaded. Open BoneMenu -> CustomFov.");
}
public override void OnLateUpdate()
{
try
{
FovController.Tick();
Settings.Tick();
}
catch (Exception ex)
{
float realtimeSinceStartup = Time.realtimeSinceStartup;
if (realtimeSinceStartup > _nextErrorLog)
{
_nextErrorLog = realtimeSinceStartup + 5f;
MelonLogger.Error("[CustomFov] tick error: " + ex);
}
}
}
}
public static class Settings
{
private static MelonPreferences_Category _cat;
private static float _saveAt = -1f;
private static bool _suppress;
public static MelonPreferences_Entry<bool> Override;
public static MelonPreferences_Entry<float> Fov;
private static readonly float[] Steps = new float[2] { 1f, 10f };
private static readonly FloatElement[] _rows = (FloatElement[])(object)new FloatElement[Steps.Length];
public static void Init()
{
_cat = MelonPreferences.CreateCategory("CustomFov");
Override = _cat.CreateEntry<bool>("OverrideFov", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
Fov = _cat.CreateEntry<float>("Fov", 90f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
}
public static void BuildMenu()
{
//IL_000a: 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_0091: Unknown result type (might be due to invalid IL or missing references)
Page val = Page.Root.CreatePage("CustomFov", Color.cyan, 0, true);
for (int i = 0; i < Steps.Length; i++)
{
_rows[i] = val.CreateFloat("FOV +/- " + (int)Steps[i], Color.white, Fov.Value, Steps[i], 10f, 170f, (Action<float>)OnFovChanged);
}
val.CreateFunction("Reset", Color.yellow, (Action)FovController.ResetToGame);
}
private static void OnFovChanged(float v)
{
if (!_suppress)
{
Fov.Value = v;
Override.Value = true;
ShowFov(v);
Dirty();
}
}
public static void ShowFov(float v)
{
bool suppress = _suppress;
_suppress = true;
try
{
for (int i = 0; i < _rows.Length; i++)
{
FloatElement val = _rows[i];
if (val != null && !Mathf.Approximately(val.Value, v))
{
val.Value = v;
}
}
}
finally
{
_suppress = suppress;
}
}
public static void Tick()
{
if (_saveAt > 0f && Time.realtimeSinceStartup >= _saveAt)
{
_saveAt = -1f;
MelonPreferences.Save();
}
}
public static void Dirty()
{
_saveAt = Time.realtimeSinceStartup + 1.5f;
}
}
}