using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Cinemachine;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CameraUnlock")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("CameraUnlock")]
[assembly: AssemblyTitle("CameraUnlock")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace CameraUnlock;
internal sealed class FreeCamera
{
private const float MaxPitch = 89f;
private const float SpeedStepPerNotch = 1.2f;
private const float MinSpeedScale = 0.05f;
private const float MaxSpeedScale = 20f;
private Camera _camera;
private CinemachineBrain _brain;
private bool _brainWasEnabled;
private float _gameFov;
private Vector3 _position;
private Vector3 _targetPosition;
private float _yaw;
private float _targetYaw;
private float _pitch;
private float _targetPitch;
private float _fov;
private float _speedScale = 1f;
public static bool IsActive { get; private set; }
private static Plugin Settings => Plugin.Instance;
public bool TryEnter(out string error)
{
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: 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)
//IL_008f: 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_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
error = null;
if ((Object)(object)GameAccess.LocalPlayer == (Object)null)
{
error = "join a world first";
return false;
}
if (GameAccess.IsPlayerOnSwan())
{
error = "not available on the swan boat";
return false;
}
Camera main = Camera.main;
CinemachineBrain val = (((Object)(object)main != (Object)null) ? ((Component)main).GetComponent<CinemachineBrain>() : null);
if ((Object)(object)val == (Object)null || !((Behaviour)val).enabled)
{
error = "the game camera is not available right now";
return false;
}
_camera = main;
_brain = val;
_brainWasEnabled = ((Behaviour)val).enabled;
((Behaviour)val).enabled = false;
Transform transform = ((Component)main).transform;
_position = (_targetPosition = transform.position);
Quaternion rotation = transform.rotation;
Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles;
_yaw = (_targetYaw = eulerAngles.y);
_pitch = (_targetPitch = Mathf.Clamp(Mathf.DeltaAngle(0f, eulerAngles.x), -89f, 89f));
_fov = (_gameFov = main.fieldOfView);
IsActive = true;
return true;
}
public void Exit()
{
if (IsActive)
{
IsActive = false;
if ((Object)(object)_camera != (Object)null)
{
_camera.fieldOfView = _gameFov;
}
if ((Object)(object)_brain != (Object)null)
{
((Behaviour)_brain).enabled = _brainWasEnabled;
}
_camera = null;
_brain = null;
}
}
public void ResetFov()
{
_fov = _gameFov;
Plugin.Toast($"Field of view: {_fov:0}° (default)");
}
public bool LateTick()
{
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: 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)
if (!IsActive)
{
return true;
}
if ((Object)(object)_camera == (Object)null || (Object)(object)_brain == (Object)null || (Object)(object)GameAccess.LocalPlayer == (Object)null)
{
Exit();
return false;
}
((Behaviour)_brain).enabled = false;
float unscaledDeltaTime = Time.unscaledDeltaTime;
if (!GameAccess.IsAnyTextFieldFocused())
{
ReadInput(unscaledDeltaTime);
}
float value = Settings.FreeCamSmoothing.Value;
float num = ((value <= 0f) ? 1f : (1f - Mathf.Pow(value, unscaledDeltaTime * 10f)));
_position = Vector3.Lerp(_position, _targetPosition, num);
_yaw = Mathf.Lerp(_yaw, _targetYaw, num);
_pitch = Mathf.Lerp(_pitch, _targetPitch, num);
((Component)_camera).transform.SetPositionAndRotation(_position, Quaternion.Euler(_pitch, _yaw, 0f));
_camera.fieldOfView = _fov;
return true;
}
private void ReadInput(float deltaTime)
{
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_0150: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: 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_021c: Unknown result type (might be due to invalid IL or missing references)
//IL_0267: Unknown result type (might be due to invalid IL or missing references)
//IL_0291: Unknown result type (might be due to invalid IL or missing references)
//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
bool flag = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
if (Input.GetMouseButton(1))
{
float value = Settings.FreeCamLookSensitivity.Value;
float num = (Settings.FreeCamInvertY.Value ? (-1f) : 1f);
_targetYaw += Input.GetAxisRaw("Mouse X") * value;
_targetPitch = Mathf.Clamp(_targetPitch - Input.GetAxisRaw("Mouse Y") * value * num, -89f, 89f);
}
float y = Input.mouseScrollDelta.y;
if (Mathf.Abs(y) > 0.001f && !GameAccess.IsPointerOverUi())
{
if (flag)
{
_fov = Mathf.Clamp(_fov - y * 2f, 10f, 120f);
Plugin.Toast($"Field of view: {_fov:0}°");
}
else
{
_speedScale = Mathf.Clamp(_speedScale * Mathf.Pow(1.2f, y), 0.05f, 20f);
Plugin.Toast($"Camera speed: {Settings.FreeCamSpeed.Value * _speedScale:0.##} m/s");
}
}
Vector3 zero = Vector3.zero;
if (Input.GetKey(Settings.FreeCamForward.Value))
{
zero.z += 1f;
}
if (Input.GetKey(Settings.FreeCamBack.Value))
{
zero.z -= 1f;
}
if (Input.GetKey(Settings.FreeCamRight.Value))
{
zero.x += 1f;
}
if (Input.GetKey(Settings.FreeCamLeft.Value))
{
zero.x -= 1f;
}
float num2 = 0f;
if (Input.GetKey(Settings.FreeCamUp.Value))
{
num2 += 1f;
}
if (Input.GetKey(Settings.FreeCamDown.Value))
{
num2 -= 1f;
}
if (((Vector3)(ref zero)).sqrMagnitude > 1f)
{
((Vector3)(ref zero)).Normalize();
}
float num3 = Settings.FreeCamSpeed.Value * _speedScale;
if (Input.GetKey(Settings.FreeCamFast.Value))
{
num3 *= Settings.FreeCamFastMultiplier.Value;
}
if (Input.GetKey(Settings.FreeCamSlow.Value))
{
num3 *= Settings.FreeCamSlowMultiplier.Value;
}
Vector3 val = Quaternion.Euler(_targetPitch, _targetYaw, 0f) * zero + Vector3.up * num2;
_targetPosition += val * (num3 * deltaTime);
}
}
internal static class InputBlocker
{
private static readonly string[] KeptInputs = new string[5] { "IsMouseButton1", "IsMouseButton1Up", "IsEscapeKeyDown", "EnterKeyDown", "EnterKeyUp" };
private static List<FieldInfo> _fields;
internal static void AfterInputUpdate(InputManager input)
{
if (!FreeCamera.IsActive)
{
return;
}
if (_fields == null)
{
_fields = FindInputFields();
}
foreach (FieldInfo field in _fields)
{
field.SetValue(input, (field.FieldType == typeof(bool)) ? ((object)false) : ((object)0f));
}
}
private static List<FieldInfo> FindInputFields()
{
List<FieldInfo> list = new List<FieldInfo>();
FieldInfo[] fields = typeof(InputManager).GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (fieldInfo.Name.StartsWith("<") && fieldInfo.Name.EndsWith(">k__BackingField") && (!(fieldInfo.FieldType != typeof(bool)) || !(fieldInfo.FieldType != typeof(float))))
{
string value = fieldInfo.Name.Substring(1, fieldInfo.Name.IndexOf('>') - 1);
if (Array.IndexOf(KeptInputs, value) < 0)
{
list.Add(fieldInfo);
}
}
}
return list;
}
}
internal static class GameAccess
{
private const float LookupInterval = 1f;
private static TextChannelManager _chat;
private static float _nextChatLookup;
private static TextChannelManager Chat
{
get
{
if ((Object)(object)_chat == (Object)null && Time.unscaledTime >= _nextChatLookup)
{
_nextChatLookup = Time.unscaledTime + 1f;
_chat = NetworkSingleton<TextChannelManager>.I;
}
return _chat;
}
}
public static Transform LocalPlayer
{
get
{
TextChannelManager chat = Chat;
if (!((Object)(object)chat != (Object)null))
{
return null;
}
return chat.MainPlayer;
}
}
public static bool IsPlayerOnSwan()
{
if ((Object)(object)LocalPlayer == (Object)null)
{
return false;
}
SwanManager i = NetworkSingleton<SwanManager>.I;
if ((Object)(object)i != (Object)null)
{
return i.IsPlayerOnSwan();
}
return false;
}
public static bool IsAnyTextFieldFocused()
{
EventSystem current = EventSystem.current;
if ((Object)(object)current == (Object)null)
{
return false;
}
GameObject currentSelectedGameObject = current.currentSelectedGameObject;
if ((Object)(object)currentSelectedGameObject == (Object)null)
{
return false;
}
TMP_InputField component = currentSelectedGameObject.GetComponent<TMP_InputField>();
if ((Object)(object)component != (Object)null && component.isFocused)
{
return true;
}
InputField component2 = currentSelectedGameObject.GetComponent<InputField>();
if ((Object)(object)component2 != (Object)null)
{
return component2.isFocused;
}
return false;
}
public static bool IsPointerOverUi()
{
EventSystem current = EventSystem.current;
if ((Object)(object)current != (Object)null)
{
return current.IsPointerOverGameObject();
}
return false;
}
public static bool GameWouldZoom()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Invalid comparison between Unknown and I4
if ((int)MonoSingleton<OverlayManager>.I.ResolutionMode == 3)
{
return false;
}
GameObject mouseOverUIObject = MonoSingleton<InputManager>.I.MouseOverUIObject;
if (!((Object)(object)mouseOverUIObject == (Object)null))
{
return MonoSingleton<UIManager>.I.OverlayMasks.Contains(mouseOverUIObject.transform);
}
return true;
}
}
internal static class Lens
{
public const float MinFov = 10f;
public const float MaxFov = 120f;
public const float StepPerNotch = 2f;
private static CinemachineVirtualCamera _vcam;
private static float _gameFov;
private static float? _wheelFov;
private static bool _modified;
private static Plugin Settings => Plugin.Instance;
public static void Adjust(CinemachineVirtualCamera vcam, float scroll)
{
if (!((Object)(object)vcam == (Object)null))
{
Capture(vcam);
_wheelFov = Mathf.Clamp(TargetFov() - scroll * 2f, 10f, 120f);
Plugin.Toast($"Field of view: {_wheelFov.Value:0}°");
}
}
public static void Reset()
{
_wheelFov = null;
if ((Object)(object)_vcam != (Object)null)
{
Plugin.Toast($"Field of view: {TargetFov():0}° (default)");
}
}
public static void Tick(CinemachineVirtualCamera vcam)
{
if (!((Object)(object)vcam == (Object)null))
{
Capture(vcam);
float num = TargetFov();
if (_modified || !Mathf.Approximately(num, _gameFov))
{
SetFov(vcam, num);
_modified = !Mathf.Approximately(num, _gameFov);
}
}
}
public static void Restore()
{
_wheelFov = null;
if ((Object)(object)_vcam != (Object)null && _modified)
{
SetFov(_vcam, _gameFov);
}
_modified = false;
}
private static void Capture(CinemachineVirtualCamera vcam)
{
if (!((Object)(object)vcam == (Object)(object)_vcam))
{
_vcam = vcam;
_gameFov = vcam.m_Lens.FieldOfView;
_modified = false;
}
}
private static float TargetFov()
{
if (_wheelFov.HasValue)
{
return _wheelFov.Value;
}
float value = Settings.FieldOfView.Value;
if (!(value >= 10f))
{
return _gameFov;
}
return Mathf.Min(value, 120f);
}
private static void SetFov(CinemachineVirtualCamera vcam, float fov)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
LensSettings lens = vcam.m_Lens;
if (!Mathf.Approximately(lens.FieldOfView, fov))
{
lens.FieldOfView = fov;
vcam.m_Lens = lens;
}
}
}
internal static class OrbitCamera
{
private const float GameShoulderRadius = 2f;
private const float GameMouseToY = 0.05f;
private const float DegreesPerY = 28.64789f;
private static readonly FieldRef<PlayerMovementController, float> CurrentZoomRef = AccessTools.FieldRefAccess<PlayerMovementController, float>("_currentZoom");
private static readonly FieldRef<PlayerMovementController, CinemachineVirtualCamera> VcamRef = AccessTools.FieldRefAccess<PlayerMovementController, CinemachineVirtualCamera>("_cinemachineVC");
private static PlayerMovementController _controller;
private static bool _engaged;
private static float _pitch;
private static float _distance;
private static float _lastGameY;
public static CinemachineVirtualCamera Vcam { get; private set; }
private static Plugin Settings => Plugin.Instance;
internal static void BeforeRotation(PlayerMovementController controller, Vector2 mouseDelta)
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
Vcam = VcamRef.Invoke(controller);
if (Settings.OrbitEnabled.Value)
{
if (!_engaged || (Object)(object)controller != (Object)(object)_controller)
{
Engage(controller);
}
else if (!Mathf.Approximately(controller.RotationXPosY, _lastGameY))
{
FollowGameTilt(controller);
}
float num = (0f - mouseDelta.y) * ScriptableSingleton<GameSettings>.I.CameraRotateSpeed * 0.05f;
_pitch = ClampPitch(_pitch + num * 28.64789f * Settings.PitchSensitivity.Value);
}
}
internal static void OnZoom(PlayerMovementController controller)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
float y = Input.mouseScrollDelta.y;
if (Mathf.Abs(y) < 0.001f || !GameAccess.GameWouldZoom())
{
return;
}
if (MonoSingleton<InputManager>.I.IsShiftKey)
{
if (Settings.ShiftScrollFov.Value)
{
Lens.Adjust(VcamRef.Invoke(controller), y);
}
}
else if (Settings.OrbitEnabled.Value && _engaged && !((Object)(object)controller != (Object)(object)_controller))
{
float num = 1f + Settings.ZoomStep.Value / 100f;
_distance = ClampDistance(_distance * Mathf.Pow(num, 0f - y));
}
}
internal static void Apply(PlayerMovementController controller)
{
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
if (Settings.OrbitEnabled.Value && _engaged && !((Object)(object)controller != (Object)(object)_controller))
{
Cinemachine3rdPersonFollow val = FollowOf(controller);
if (!((Object)(object)val == (Object)null))
{
_pitch = ClampPitch(_pitch);
_distance = ClampDistance(_distance);
float num = _pitch * (MathF.PI / 180f);
val.ShoulderOffset = new Vector3(val.ShoulderOffset.x, _distance * Mathf.Sin(num), (0f - _distance) * Mathf.Cos(num));
val.CameraDistance = 0f;
_lastGameY = controller.RotationXPosY;
}
}
}
internal static void Disengage()
{
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
if (!_engaged)
{
return;
}
_engaged = false;
PlayerMovementController controller = _controller;
_controller = null;
if (!((Object)(object)controller == (Object)null))
{
Cinemachine3rdPersonFollow val = FollowOf(controller);
if ((Object)(object)val != (Object)null)
{
val.CameraDistance = CurrentZoomRef.Invoke(controller);
}
controller.SetCameraRotation(Vector2.zero);
}
}
private static void Engage(PlayerMovementController controller)
{
_controller = controller;
_engaged = true;
float rotationXPosY = controller.RotationXPosY;
float num = VanillaBackOffset(controller, rotationXPosY);
_pitch = ClampPitch(Mathf.Atan2(rotationXPosY, num) * 57.29578f);
_distance = ClampDistance(Mathf.Sqrt(rotationXPosY * rotationXPosY + num * num));
_lastGameY = rotationXPosY;
}
private static void FollowGameTilt(PlayerMovementController controller)
{
float rotationXPosY = controller.RotationXPosY;
_pitch = ClampPitch(Mathf.Atan2(rotationXPosY, VanillaBackOffset(controller, rotationXPosY)) * 57.29578f);
_lastGameY = rotationXPosY;
}
private static float VanillaBackOffset(PlayerMovementController controller, float y)
{
return Mathf.Sqrt(Mathf.Max(0f, 4f - y * y)) + Mathf.Max(0f, CurrentZoomRef.Invoke(controller));
}
private static Cinemachine3rdPersonFollow FollowOf(PlayerMovementController controller)
{
CinemachineVirtualCamera val = VcamRef.Invoke(controller);
if (!((Object)(object)val != (Object)null))
{
return null;
}
return val.GetCinemachineComponent<Cinemachine3rdPersonFollow>();
}
private static float ClampPitch(float pitch)
{
float value = Settings.MinPitch.Value;
float num = Mathf.Max(value, Settings.MaxPitch.Value);
return Mathf.Clamp(pitch, value, num);
}
private static float ClampDistance(float distance)
{
float value = Settings.MinDistance.Value;
float num = Mathf.Max(value, Settings.MaxDistance.Value);
return Mathf.Clamp(distance, value, num);
}
}
[BepInPlugin("ontogether.cameraunlock", "CameraUnlock", "1.0.1")]
[BepInProcess("OnTogether.exe")]
public sealed class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "ontogether.cameraunlock";
public const string PluginName = "CameraUnlock";
public const string PluginVersion = "1.0.1";
private const float ToastDuration = 2f;
private const float FreeCamHintDuration = 7f;
internal ConfigEntry<bool> OrbitEnabled;
internal ConfigEntry<float> MinDistance;
internal ConfigEntry<float> MaxDistance;
internal ConfigEntry<float> MinPitch;
internal ConfigEntry<float> MaxPitch;
internal ConfigEntry<float> ZoomStep;
internal ConfigEntry<float> PitchSensitivity;
internal ConfigEntry<bool> CameraCollision;
internal ConfigEntry<float> FieldOfView;
internal ConfigEntry<bool> ShiftScrollFov;
internal ConfigEntry<KeyboardShortcut> FreeCamToggleKey;
internal ConfigEntry<float> FreeCamSpeed;
internal ConfigEntry<float> FreeCamFastMultiplier;
internal ConfigEntry<float> FreeCamSlowMultiplier;
internal ConfigEntry<float> FreeCamLookSensitivity;
internal ConfigEntry<bool> FreeCamInvertY;
internal ConfigEntry<float> FreeCamSmoothing;
internal ConfigEntry<bool> HideUiInFreeCam;
internal ConfigEntry<KeyCode> FreeCamForward;
internal ConfigEntry<KeyCode> FreeCamBack;
internal ConfigEntry<KeyCode> FreeCamLeft;
internal ConfigEntry<KeyCode> FreeCamRight;
internal ConfigEntry<KeyCode> FreeCamUp;
internal ConfigEntry<KeyCode> FreeCamDown;
internal ConfigEntry<KeyCode> FreeCamFast;
internal ConfigEntry<KeyCode> FreeCamSlow;
internal ConfigEntry<KeyboardShortcut> HideUiKey;
internal ConfigEntry<bool> HideWorldSpaceUi;
internal ConfigEntry<bool> ShowHints;
private Harmony _harmony;
private readonly FreeCamera _freeCamera = new FreeCamera();
private readonly UiHider _uiHider = new UiHider();
private bool _uiHiddenByFreeCam;
private readonly ColliderSwitch _collider = new ColliderSwitch();
private static string _toast;
private static float _toastUntil;
private float _hintUntil;
private GUIStyle _hintStyle;
private static string _lastError;
internal static Plugin Instance { get; private set; }
internal static ManualLogSource Log { get; private set; }
private void Awake()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
BindConfig();
_harmony = new Harmony("ontogether.cameraunlock");
TryPatch(typeof(SetCameraRotationPatch), "camera tilt");
TryPatch(typeof(ZoomPatch), "camera zoom");
TryPatch(typeof(InputManagerUpdatePatch), "input blocking for the free camera");
OrbitEnabled.SettingChanged += delegate
{
if (!OrbitEnabled.Value)
{
OrbitCamera.Disengage();
}
};
Log.LogInfo((object)string.Format("{0} {1} loaded. Free camera: {2}, hide UI: {3}", "CameraUnlock", "1.0.1", FreeCamToggleKey.Value, HideUiKey.Value));
}
private void BindConfig()
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Expected O, but got Unknown
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Expected O, but got Unknown
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Expected O, but got Unknown
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Expected O, but got Unknown
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Expected O, but got Unknown
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Expected O, but got Unknown
//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
//IL_01ef: Expected O, but got Unknown
//IL_0230: Unknown result type (might be due to invalid IL or missing references)
//IL_0273: Unknown result type (might be due to invalid IL or missing references)
//IL_027d: Expected O, but got Unknown
//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
//IL_02bb: Expected O, but got Unknown
//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
//IL_02f9: Expected O, but got Unknown
//IL_032d: Unknown result type (might be due to invalid IL or missing references)
//IL_0337: Expected O, but got Unknown
//IL_038c: Unknown result type (might be due to invalid IL or missing references)
//IL_0396: Expected O, but got Unknown
//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
OrbitEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Orbit", "Enabled", true, "Replace the game's short zoom and tilt range with a free orbit around your character (mouse wheel = distance, right mouse button = tilt). Off: the game's own camera.");
MinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Orbit", "MinDistance", 0.4f, new ConfigDescription("Closest camera distance in metres (the game: about 2.3).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
MaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Orbit", "MaxDistance", 40f, new ConfigDescription("Farthest camera distance in metres (the game: about 4.3).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 300f), Array.Empty<object>()));
MinPitch = ((BaseUnityPlugin)this).Config.Bind<float>("Orbit", "MinPitch", -75f, new ConfigDescription("Lowest camera angle in degrees; negative looks up at your character from below.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-89f, 0f), Array.Empty<object>()));
MaxPitch = ((BaseUnityPlugin)this).Config.Bind<float>("Orbit", "MaxPitch", 89f, new ConfigDescription("Highest camera angle in degrees; 89 is a straight top-down view.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 89f), Array.Empty<object>()));
ZoomStep = ((BaseUnityPlugin)this).Config.Bind<float>("Orbit", "ZoomStepPercent", 12f, new ConfigDescription("How much one wheel notch changes the distance, in percent.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), Array.Empty<object>()));
PitchSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("Orbit", "TiltSensitivity", 1f, new ConfigDescription("Multiplier for vertical mouse movement (1 = like the game near the horizon).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
CameraCollision = ((BaseUnityPlugin)this).Config.Bind<bool>("Orbit", "CameraCollision", true, "Keep the camera in front of walls and the ground, as the game does. Turn off to see through walls.");
FieldOfView = ((BaseUnityPlugin)this).Config.Bind<float>("Lens", "FieldOfView", 0f, new ConfigDescription("Vertical field of view of the normal camera in degrees; 0 = the game's default.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), Array.Empty<object>()));
ShiftScrollFov = ((BaseUnityPlugin)this).Config.Bind<bool>("Lens", "ShiftWheelChangesFov", true, "Shift + mouse wheel changes the field of view (both cameras); Shift + middle click resets it.");
FreeCamToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("FreeCamera", "ToggleKey", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Turns the free camera on/off (ignored while typing). Your character stays in place.");
FreeCamSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("FreeCamera", "Speed", 4f, new ConfigDescription("Flying speed in metres per second (the mouse wheel scales it while flying).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 100f), Array.Empty<object>()));
FreeCamFastMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("FreeCamera", "FastMultiplier", 4f, new ConfigDescription("Speed multiplier while the Fast key is held.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
FreeCamSlowMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("FreeCamera", "SlowMultiplier", 0.25f, new ConfigDescription("Speed multiplier while the Slow key is held.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
FreeCamLookSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("FreeCamera", "LookSensitivity", 2f, new ConfigDescription("Mouse look sensitivity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), Array.Empty<object>()));
FreeCamInvertY = ((BaseUnityPlugin)this).Config.Bind<bool>("FreeCamera", "InvertY", false, "Invert vertical mouse look.");
FreeCamSmoothing = ((BaseUnityPlugin)this).Config.Bind<float>("FreeCamera", "Smoothing", 0f, new ConfigDescription("Smooth, cinematic movement: 0 = none, 0.9 = very smooth.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.98f), Array.Empty<object>()));
HideUiInFreeCam = ((BaseUnityPlugin)this).Config.Bind<bool>("FreeCamera", "HideUiWhileFlying", false, "Hide the interface automatically while the free camera is on.");
FreeCamForward = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("FreeCamera.Keys", "Forward", (KeyCode)119, "Fly forward.");
FreeCamBack = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("FreeCamera.Keys", "Back", (KeyCode)115, "Fly back.");
FreeCamLeft = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("FreeCamera.Keys", "Left", (KeyCode)97, "Fly left.");
FreeCamRight = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("FreeCamera.Keys", "Right", (KeyCode)100, "Fly right.");
FreeCamUp = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("FreeCamera.Keys", "Up", (KeyCode)101, "Fly straight up.");
FreeCamDown = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("FreeCamera.Keys", "Down", (KeyCode)113, "Fly straight down.");
FreeCamFast = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("FreeCamera.Keys", "Fast", (KeyCode)304, "Hold to fly faster.");
FreeCamSlow = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("FreeCamera.Keys", "Slow", (KeyCode)306, "Hold to fly slower.");
HideUiKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Screenshots", "HideUiKey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Hides/shows the game's interface (ignored while typing).");
HideWorldSpaceUi = ((BaseUnityPlugin)this).Config.Bind<bool>("Screenshots", "HideWorldSpaceUi", false, "Also hide interface elements placed in the world (signs, screens and labels drawn with canvases).");
ShowHints = ((BaseUnityPlugin)this).Config.Bind<bool>("Screenshots", "ShowHints", true, "Show short on-screen hints (controls, field of view, speed). Never drawn while the interface is hidden.");
}
private void TryPatch(Type patch, string feature)
{
try
{
_harmony.CreateClassProcessor(patch).Patch();
}
catch (Exception arg)
{
Log.LogError((object)$"Could not patch the game for {feature}; that part will not work: {arg}");
}
}
private void Update()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
if (GameAccess.IsAnyTextFieldFocused())
{
return;
}
ReadShortcuts(FreeCamToggleKey.Value, HideUiKey.Value, out var firstPressed, out var secondPressed);
if (firstPressed)
{
ToggleFreeCamera();
}
if (secondPressed)
{
if (_uiHider.IsHidden)
{
_uiHider.Show();
}
else
{
_uiHider.Hide();
}
_uiHiddenByFreeCam = false;
}
if (ShiftScrollFov.Value && Input.GetMouseButtonDown(2) && (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)))
{
if (FreeCamera.IsActive)
{
_freeCamera.ResetFov();
}
else
{
Lens.Reset();
}
}
}
private static void ReadShortcuts(KeyboardShortcut first, KeyboardShortcut second, out bool firstPressed, out bool secondPressed)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
firstPressed = Pressed(first);
secondPressed = Pressed(second);
if (firstPressed && secondPressed && ((KeyboardShortcut)(ref first)).MainKey == ((KeyboardShortcut)(ref second)).MainKey)
{
int num = ((KeyboardShortcut)(ref first)).Modifiers.Count() - ((KeyboardShortcut)(ref second)).Modifiers.Count();
firstPressed = num >= 0;
secondPressed = num <= 0;
}
}
private static bool Pressed(KeyboardShortcut shortcut)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
KeyCode mainKey = ((KeyboardShortcut)(ref shortcut)).MainKey;
if ((int)mainKey == 0 || !Input.GetKeyDown(mainKey))
{
return false;
}
foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
{
if (!Input.GetKey(modifier))
{
return false;
}
}
return true;
}
private void LateUpdate()
{
try
{
if (!_freeCamera.LateTick())
{
OnFreeCameraEnded("Free camera: off (the camera changed)");
}
Lens.Tick(OrbitCamera.Vcam);
_collider.Apply(OrbitCamera.Vcam, CameraCollision.Value);
_uiHider.Tick();
}
catch (Exception e)
{
LogOnce(e);
}
}
internal static void LogOnce(Exception e)
{
string text = e.GetType().Name + ": " + e.Message;
if (!(text == _lastError))
{
_lastError = text;
Log.LogError((object)e);
}
}
private void ToggleFreeCamera()
{
if (FreeCamera.IsActive)
{
_freeCamera.Exit();
OnFreeCameraEnded("Free camera: off");
return;
}
if (!_freeCamera.TryEnter(out var error))
{
Toast("Free camera: " + error);
return;
}
if (HideUiInFreeCam.Value && !_uiHider.IsHidden)
{
_uiHider.Hide();
_uiHiddenByFreeCam = true;
}
_hintUntil = Time.unscaledTime + 7f;
_toastUntil = 0f;
}
private void OnFreeCameraEnded(string message)
{
if (_uiHiddenByFreeCam)
{
_uiHider.Show();
}
_uiHiddenByFreeCam = false;
_hintUntil = 0f;
Toast(message);
}
internal static void Toast(string message)
{
_toast = message;
_toastUntil = Time.unscaledTime + 2f;
}
private string FreeCamHint()
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: 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_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: 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)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
return $"Free camera — {FreeCamForward.Value}/{FreeCamLeft.Value}/{FreeCamBack.Value}/{FreeCamRight.Value} fly, " + $"{FreeCamUp.Value}/{FreeCamDown.Value} up/down, hold right mouse to look, " + $"{FreeCamFast.Value} fast, {FreeCamSlow.Value} slow, wheel = speed, Shift + wheel = zoom (FOV), " + $"{HideUiKey.Value} hide UI, {FreeCamToggleKey.Value} back to the character";
}
private void OnGUI()
{
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Expected O, but got Unknown
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Expected O, but got Unknown
//IL_0146: 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_0064: 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_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Expected O, but got Unknown
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
if (!ShowHints.Value || _uiHider.IsHidden)
{
return;
}
float unscaledTime = Time.unscaledTime;
string text = ((unscaledTime < _toastUntil) ? _toast : ((unscaledTime < _hintUntil) ? FreeCamHint() : null));
if (!string.IsNullOrEmpty(text))
{
if (_hintStyle == null)
{
_hintStyle = new GUIStyle(GUI.skin.box)
{
alignment = (TextAnchor)4,
wordWrap = true,
richText = false
};
_hintStyle.normal.textColor = Color.white;
}
float num = Mathf.Max(1f, (float)Screen.height / 1080f);
_hintStyle.fontSize = Mathf.RoundToInt(16f * num);
_hintStyle.padding = new RectOffset(Mathf.RoundToInt(12f * num), Mathf.RoundToInt(12f * num), Mathf.RoundToInt(8f * num), Mathf.RoundToInt(8f * num));
float num2 = Mathf.Min((float)Screen.width - 32f, 900f * num);
float num3 = _hintStyle.CalcHeight(new GUIContent(text), num2);
GUI.Box(new Rect(((float)Screen.width - num2) / 2f, 24f * num, num2, num3), text, _hintStyle);
}
}
private void OnDestroy()
{
try
{
_freeCamera.Exit();
_uiHider.Show();
OrbitCamera.Disengage();
Lens.Restore();
_collider.Restore();
}
catch (Exception ex)
{
Log.LogDebug((object)("Cleanup skipped: " + ex.Message));
}
if (_harmony != null)
{
_harmony.UnpatchSelf();
}
}
}
internal sealed class ColliderSwitch
{
private CinemachineCollider _collider;
private bool _gameEnabled;
public void Apply(CinemachineVirtualCamera vcam, bool enabled)
{
if ((Object)(object)vcam == (Object)null)
{
return;
}
if ((Object)(object)_collider == (Object)null || (Object)(object)((Component)_collider).gameObject != (Object)(object)((Component)vcam).gameObject)
{
_collider = ((Component)vcam).GetComponent<CinemachineCollider>();
if ((Object)(object)_collider == (Object)null)
{
return;
}
_gameEnabled = ((Behaviour)_collider).enabled;
}
bool flag = enabled && _gameEnabled;
if (((Behaviour)_collider).enabled != flag)
{
((Behaviour)_collider).enabled = flag;
}
}
public void Restore()
{
if ((Object)(object)_collider != (Object)null)
{
((Behaviour)_collider).enabled = _gameEnabled;
}
}
}
[HarmonyPatch(typeof(PlayerMovementController), "SetCameraRotation")]
internal static class SetCameraRotationPatch
{
private static void Prefix(PlayerMovementController __instance, Vector2 mouseDelta)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
try
{
OrbitCamera.BeforeRotation(__instance, mouseDelta);
}
catch (Exception e)
{
Plugin.LogOnce(e);
}
}
private static void Postfix(PlayerMovementController __instance)
{
try
{
OrbitCamera.Apply(__instance);
}
catch (Exception e)
{
Plugin.LogOnce(e);
}
}
}
[HarmonyPatch(typeof(PlayerMovementController), "Zoom")]
internal static class ZoomPatch
{
private static bool Prefix(PlayerMovementController __instance)
{
if (FreeCamera.IsActive)
{
return false;
}
try
{
OrbitCamera.OnZoom(__instance);
}
catch (Exception e)
{
Plugin.LogOnce(e);
}
return true;
}
private static void Postfix(PlayerMovementController __instance)
{
try
{
OrbitCamera.Apply(__instance);
}
catch (Exception e)
{
Plugin.LogOnce(e);
}
}
}
[HarmonyPatch(typeof(InputManager), "Update")]
internal static class InputManagerUpdatePatch
{
private static void Postfix(InputManager __instance)
{
try
{
InputBlocker.AfterInputUpdate(__instance);
}
catch (Exception e)
{
Plugin.LogOnce(e);
}
}
}
internal sealed class UiHider
{
private const float RescanInterval = 0.5f;
private readonly List<Behaviour> _disabled = new List<Behaviour>();
private float _nextScan;
public bool IsHidden { get; private set; }
public void Hide()
{
if (!IsHidden)
{
IsHidden = true;
Scan();
}
}
public void Show()
{
if (!IsHidden)
{
return;
}
IsHidden = false;
foreach (Behaviour item in _disabled)
{
if ((Object)(object)item != (Object)null)
{
item.enabled = true;
}
}
_disabled.Clear();
}
public void Tick()
{
if (IsHidden && Time.unscaledTime >= _nextScan)
{
Scan();
}
}
private void Scan()
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Invalid comparison between Unknown and I4
_nextScan = Time.unscaledTime + 0.5f;
bool value = Plugin.Instance.HideWorldSpaceUi.Value;
Canvas[] array = Object.FindObjectsByType<Canvas>((FindObjectsSortMode)0);
foreach (Canvas val in array)
{
if (!((Behaviour)val).enabled || !val.isRootCanvas || ((int)val.renderMode == 2 && !value))
{
continue;
}
((Behaviour)val).enabled = false;
_disabled.Add((Behaviour)(object)val);
BaseRaycaster[] components = ((Component)val).GetComponents<BaseRaycaster>();
foreach (BaseRaycaster val2 in components)
{
if (((Behaviour)val2).enabled)
{
((Behaviour)val2).enabled = false;
_disabled.Add((Behaviour)(object)val2);
}
}
}
}
}