Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of FirstPerson v1.0.14
Landoria.FirstPerson.dll
Decompiled 4 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Landoria.Shared; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Landoria.FirstPerson")] [assembly: AssemblyDescription("Adds first-person view and persistent normal-camera FOV control.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Landoria")] [assembly: AssemblyProduct("Landoria.FirstPerson")] [assembly: AssemblyCopyright("Copyright © 2026 End3rbyte")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("E3AE6231-B01C-4392-AA43-20F1215A876B")] [assembly: AssemblyFileVersion("1.0.14")] [assembly: AssemblyInformationalVersion("1.0.14")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.14.28373")] namespace Landoria.Shared { internal static class ConfigWatcher { private const int ReloadDelayMilliseconds = 250; private const int MaximumReloadAttempts = 5; private static ConfigFile config; private static string configPath; private static ManualLogSource logger; private static FileSystemWatcher watcher; private static long lastChangeTicks; private static int reloadPending; private static int reloadAttempts; private static long ignoredWriteTicks; private static string displayName; private static Action restoreDefaults; private static Action applyConfiguration; internal static void Initialize(ConfigFile configFile, ManualLogSource logSource, string configurationDisplayName, Action restoreDefaultsAction, Action applyConfigurationAction = null) { Dispose(); config = configFile; logger = logSource; displayName = configurationDisplayName; restoreDefaults = restoreDefaultsAction; applyConfiguration = applyConfigurationAction; configPath = Path.GetFullPath(config.ConfigFilePath); watcher = new FileSystemWatcher(Path.GetDirectoryName(configPath), Path.GetFileName(configPath)); watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime; watcher.Changed += OnChanged; watcher.Created += OnChanged; watcher.Deleted += OnChanged; watcher.Renamed += OnRenamed; watcher.EnableRaisingEvents = true; } internal static void IgnoreCurrentFileVersion() { if (string.IsNullOrEmpty(configPath) || !File.Exists(configPath)) { return; } try { Interlocked.Exchange(ref ignoredWriteTicks, File.GetLastWriteTimeUtc(configPath).Ticks); Interlocked.Exchange(ref reloadPending, 0); } catch (IOException) { ManualLogSource obj = logger; if (obj != null) { obj.LogDebug((object)"Could not mark the internal configuration write."); } } } internal static void Update() { if (Volatile.Read(in reloadPending) == 0 || !ReloadDelayElapsed()) { return; } Interlocked.Exchange(ref reloadPending, 0); try { bool flag = !File.Exists(configPath); if (flag) { restoreDefaults?.Invoke(); } else { config.Reload(); } applyConfiguration?.Invoke(); reloadAttempts = 0; logger.LogInfo((object)(flag ? "Recreated the deleted configuration with default values." : "Reloaded configuration after a file change.")); ShowReloadMessage(flag); } catch (Exception exception) { RetryReload(exception); } } internal static void Dispose() { if (watcher != null) { watcher.EnableRaisingEvents = false; watcher.Dispose(); watcher = null; } Interlocked.Exchange(ref reloadPending, 0); Interlocked.Exchange(ref ignoredWriteTicks, 0L); reloadAttempts = 0; displayName = null; restoreDefaults = null; applyConfiguration = null; } private static void OnChanged(object sender, FileSystemEventArgs eventArgs) { QueueReload(); } private static void OnRenamed(object sender, RenamedEventArgs eventArgs) { QueueReload(); } private static void QueueReload() { if (!IsIgnoredWrite()) { Interlocked.Exchange(ref lastChangeTicks, DateTime.UtcNow.Ticks); Interlocked.Exchange(ref reloadPending, 1); reloadAttempts = 0; } } private static bool IsIgnoredWrite() { try { long num = (File.Exists(configPath) ? File.GetLastWriteTimeUtc(configPath).Ticks : 0); return num != 0L && num == Interlocked.Read(in ignoredWriteTicks); } catch (IOException) { return false; } } private static bool ReloadDelayElapsed() { return DateTime.UtcNow.Ticks - Interlocked.Read(in lastChangeTicks) >= 2500000; } private static void RetryReload(Exception exception) { reloadAttempts++; logger.LogWarning((object)("Configuration reload failed: " + exception.Message)); if (reloadAttempts < 5) { Interlocked.Exchange(ref lastChangeTicks, DateTime.UtcNow.Ticks); Interlocked.Exchange(ref reloadPending, 1); } } private static void ShowReloadMessage(bool recreated) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, recreated ? (displayName + " configuration restored to defaults.") : (displayName + " configuration reloaded."), 0, (Sprite)null, false); } } } } namespace Landoria.FirstPerson { [HarmonyPatch(typeof(GameCamera), "Awake")] internal static class CameraAwakePatch { private static void Prefix(GameCamera __instance) { Mode.CaptureVanillaDistance(__instance); } private static void Postfix(GameCamera __instance) { Mode.Apply(__instance); } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] internal static class CameraUpdatePatch { private static void Prefix(ref float ___m_distance) { Shortcut.Update(ref ___m_distance); Shortcut.PrepareDistanceObservation(___m_distance); } private static void Postfix(GameCamera __instance, Camera ___m_camera, ref float ___m_distance) { Shortcut.ObserveCameraDistance(ref ___m_distance); Player localPlayer = Player.m_localPlayer; bool flag = Mode.ShouldActivate(localPlayer, GameCamera.InFreeFly(), ___m_distance); Mode.SetActive(flag); Mode.ApplyConfiguredFieldOfView(__instance); Mode.ApplyNearClipPlane(___m_camera); VisibilityController.SetHidden(localPlayer, flag); if (flag) { ViewController.Apply(__instance, localPlayer); } if (flag) { HeadBobController.Apply(__instance, localPlayer); HelmetLightController.Apply(__instance, localPlayer); } else { HeadBobController.Reset(); HelmetLightController.Restore(); } } } [HarmonyPatch(typeof(GameCamera), "GetCameraOffset")] internal static class CameraOffsetPatch { private static void Postfix(GameCamera __instance, Player player, ref Vector3 __result) { //IL_001c: 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) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (Mode.Active && Object.op_Implicit((Object)(object)player)) { Vector3 val = ((Component)((Character)player).m_eye).transform.TransformVector(__instance.m_fpsOffset); __result = val; } } } [HarmonyPatch(typeof(Player), "AlwaysRotateCamera")] internal static class PlayerRotationPatch { private static void Postfix(Player __instance, ref bool __result) { if (Mode.Active && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { __result = true; } } } [HarmonyPatch(typeof(ZNetView), "Awake")] internal static class LoadedObjectPatch { private static void Postfix(ZNetView __instance) { VegetationController.Apply(((Component)__instance).gameObject); } } [HarmonyPatch(typeof(Character), "SetVisible")] internal static class PlayerVisibilityPatch { private static void Prefix(Character __instance, ref bool visible) { if (Mode.Active && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { visible = true; } } } [HarmonyPatch(typeof(VisEquipment), "UpdateVisuals")] internal static class VisualVisibilityPatch { private static void Postfix(VisEquipment __instance, GameObject ___m_leftItemInstance, GameObject ___m_rightItemInstance) { Player componentInParent = ((Component)__instance).GetComponentInParent<Player>(); if ((Object)(object)componentInParent == (Object)(object)Player.m_localPlayer) { VisibilityController.TrackHeldItems(componentInParent, ___m_leftItemInstance, ___m_rightItemInstance); } if (Mode.Active && (Object)(object)componentInParent == (Object)(object)Player.m_localPlayer) { HelmetLightController.Refresh(componentInParent); } } } [HarmonyPatch(typeof(MonoUpdaters), "LateUpdate")] internal static class HelmetLightLateUpdatePatch { private static void Postfix() { HelmetLightController.Apply(GameCamera.instance, Player.m_localPlayer); } } [HarmonyPatch(typeof(ConsoleCommand), "RunAction")] internal static class FieldOfViewCommandPatch { private static bool Prefix(ConsoleCommand __instance, ConsoleEventArgs args) { if (__instance.Command == "fov" && args.Length == 1) { Terminal context = args.Context; if (context != null) { context.AddString($"FOV: {Preference.FieldOfView:0.#}"); } return false; } string a = ((args.Length > 1) ? args[1] : null); if (!(__instance.Command == "fov") || args.Length != 2 || !string.Equals(a, "reset", StringComparison.OrdinalIgnoreCase)) { float num = default(float); bool flag = args.TryParameterFloat(1, ref num); if (!(__instance.Command == "fov" && args.Length > 1 && flag) || (!(num < 65f) && !(num > 120f))) { return true; } Terminal context2 = args.Context; if (context2 != null) { context2.AddString($"FOV must be between {65f} " + $"and {120f}. " + "The current FOV was not changed."); } return false; } Preference.SetFieldOfView(65f); Mode.ApplyConfiguredFieldOfView(GameCamera.instance); return false; } private static void Postfix(ConsoleCommand __instance, ConsoleEventArgs args) { float num = default(float); bool flag = args.TryParameterFloat(1, ref num); if (__instance.Command == "fov" && args.Length > 1 && flag && num >= 65f && num <= 120f) { Preference.SetFieldOfView(num); Mode.ApplyConfiguredFieldOfView(GameCamera.instance); } } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class PlayerSpawnPatch { private static void Postfix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { Mode.SetEnabled(Preference.Enabled); Mode.ApplyConfiguredFieldOfView(GameCamera.instance); } } } [HarmonyPatch(typeof(ZNet), "OnDestroy")] internal static class DisconnectPatch { private static void Prefix() { Mode.ResetSession(); } } internal static class HeadBobController { private const float WalkVerticalAmplitude = 4f; private const float WalkStepInterval = 0.7f; private const float JogVerticalAmplitude = 6f; private const float JogStepInterval = 0.433f; private const float SprintVerticalAmplitude = 8f; private const float SprintStepInterval = 0.333f; private const float HorizontalAmplitude = 4f; private const float HorizonDistance = 10f; private const float MetersPerMillimeter = 0.001f; private const float MovementThreshold = 0.01f; private const float FadeDuration = 0.12f; private static float phase; private static float blend; internal static void Apply(GameCamera camera, Player player) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (Preference.HeadBobStrength > 0 && Mode.Active && Object.op_Implicit((Object)(object)camera) && Object.op_Implicit((Object)(object)player)) { int num; if (((Character)player).IsOnGround()) { Vector3 moveDir = ((Character)player).GetMoveDir(); num = ((((Vector3)(ref moveDir)).sqrMagnitude > 0.01f) ? 1 : 0); } else { num = 0; } bool flag = (byte)num != 0; blend = Mathf.MoveTowards(blend, flag ? 1f : 0f, Time.deltaTime / 0.12f); bool num2 = ((Character)player).IsRunning(); float num3 = (num2 ? 0.333f : (((Character)player).IsWalking() ? 0.7f : 0.433f)); phase = Mathf.Repeat(phase + Time.deltaTime * (float)Math.PI / num3, (float)Math.PI * 2f); float num4 = (num2 ? 8f : (((Character)player).IsWalking() ? 4f : 6f)) * 0.001f * (float)Preference.HeadBobStrength; float num5 = 0.004f * (float)Preference.HeadBobStrength; float horizontal = Mathf.Sin(phase) * num5 * blend; float vertical = Mathf.Sin(phase * 2f) * num4 * blend; ApplyMovement(((Component)camera).transform, horizontal, vertical); } } private static void ApplyMovement(Transform transform, float horizontal, float vertical) { //IL_0001: 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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = transform.position + transform.forward * 10f; transform.position += transform.right * horizontal + transform.up * vertical; transform.rotation = Quaternion.LookRotation(val - transform.position, Vector3.up); } internal static void Reset() { phase = 0f; blend = 0f; } } internal static class HelmetLightController { private struct LightState { internal Vector3 LocalPosition; internal Quaternion LocalRotation; } private struct FlickerState { internal float Intensity; internal float Movement; } private static readonly Dictionary<Light, LightState> Lights = new Dictionary<Light, LightState>(); private static readonly Dictionary<LightFlicker, FlickerState> Flickers = new Dictionary<LightFlicker, FlickerState>(); private static Player trackedPlayer; internal static void Apply(GameCamera camera, Player player) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!Mode.Active || !Object.op_Implicit((Object)(object)camera) || !Object.op_Implicit((Object)(object)player)) { Restore(); return; } if ((Object)(object)trackedPlayer != (Object)(object)player) { Refresh(player); } foreach (Light key in Lights.Keys) { if (Object.op_Implicit((Object)(object)key)) { ((Component)key).transform.SetPositionAndRotation(((Component)camera).transform.position, ((Component)camera).transform.rotation); } } } internal static void Refresh(Player player) { if (!Object.op_Implicit((Object)(object)player)) { Restore(); return; } if ((Object)(object)trackedPlayer != (Object)(object)player) { Restore(); trackedPlayer = player; } VisEquipment component = ((Component)player).GetComponent<VisEquipment>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_helmet)) { CaptureLights(component.m_helmet); CaptureFlickers(component.m_helmet); } } internal static void Restore() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<Light, LightState> light in Lights) { if (Object.op_Implicit((Object)(object)light.Key)) { ((Component)light.Key).transform.localPosition = light.Value.LocalPosition; ((Component)light.Key).transform.localRotation = light.Value.LocalRotation; } } foreach (KeyValuePair<LightFlicker, FlickerState> flicker in Flickers) { if (Object.op_Implicit((Object)(object)flicker.Key)) { flicker.Key.m_flickerIntensity = flicker.Value.Intensity; flicker.Key.m_movement = flicker.Value.Movement; } } Lights.Clear(); Flickers.Clear(); trackedPlayer = null; } private static void CaptureLights(Transform helmet) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) Light[] componentsInChildren = ((Component)helmet).GetComponentsInChildren<Light>(true); foreach (Light val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val) && !Lights.ContainsKey(val)) { Lights.Add(val, new LightState { LocalPosition = ((Component)val).transform.localPosition, LocalRotation = ((Component)val).transform.localRotation }); } } } private static void CaptureFlickers(Transform helmet) { LightFlicker[] componentsInChildren = ((Component)helmet).GetComponentsInChildren<LightFlicker>(true); foreach (LightFlicker val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val) && !Flickers.ContainsKey(val)) { Flickers.Add(val, new FlickerState { Intensity = val.m_flickerIntensity, Movement = val.m_movement }); } if (Object.op_Implicit((Object)(object)val)) { val.m_flickerIntensity = 0f; val.m_movement = 0f; } } } } internal static class Mode { private const float NearClipPlane = 0.09f; private const float DistanceThreshold = 0.001f; private static float vanillaMinimumDistance; private static bool distanceCaptured; internal static bool Enabled { get; private set; } internal static bool Active { get; private set; } internal static void CaptureVanillaDistance(GameCamera camera) { vanillaMinimumDistance = camera.m_minDistance; distanceCaptured = true; } internal static void Apply(GameCamera camera) { if (Object.op_Implicit((Object)(object)camera)) { camera.m_minDistance = (Enabled ? 0f : vanillaMinimumDistance); } } internal static void SetEnabled(bool enabled) { Enabled = enabled; if (!enabled) { SetActive(active: false); } Apply(GameCamera.instance); ApplyConfiguredFieldOfView(GameCamera.instance); } internal static void SetActive(bool active) { if (Active != active) { Active = active; if (active) { VegetationController.Apply(); } else { VegetationController.Restore(); } } } internal static bool ShouldActivate(Player player, bool isFreeFly, float cameraDistance) { if (Enabled && Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && !isFreeFly) { return IsFirstPersonDistance(cameraDistance); } return false; } internal static bool IsFirstPersonDistance(float cameraDistance) { return cameraDistance <= 0.001f; } internal static void ApplyConfiguredFieldOfView(GameCamera camera) { float num = Preference.FieldOfView; if (Active) { num += Preference.FirstPersonFieldOfViewBonus; } if (Object.op_Implicit((Object)(object)camera)) { camera.m_fov = num; } } internal static void ApplyNearClipPlane(Camera camera) { if (Active && Object.op_Implicit((Object)(object)camera)) { camera.nearClipPlane = 0.09f; } } internal static void ResetSession() { SetEnabled(enabled: false); HeadBobController.Reset(); HelmetLightController.Restore(); VisibilityController.Restore(); Shortcut.Reset(); } internal static void Reset() { ResetSession(); if (distanceCaptured && Object.op_Implicit((Object)(object)GameCamera.instance)) { GameCamera.instance.m_minDistance = vanillaMinimumDistance; } distanceCaptured = false; } } internal static class Preference { internal const float DefaultFieldOfView = 65f; internal const float MinimumFieldOfView = 65f; internal const float MaximumFieldOfView = 120f; internal const float DefaultFirstPersonFieldOfViewBonus = 15f; internal const float MaximumFirstPersonFieldOfViewBonus = 50f; internal const int DefaultThirdPersonAutoDistance = 3; internal const int DefaultAutomaticReturnDelay = 3; internal const int DefaultHeadBobStrength = 2; private static ConfigEntry<bool> enabled; private static ConfigEntry<float> fieldOfView; private static ConfigEntry<float> firstPersonFieldOfViewBonus; private static ConfigEntry<KeyboardShortcut> toggleShortcut; private static ConfigEntry<KeyboardShortcut> toggleThirdPersonAutoShortcut; private static ConfigEntry<bool> thirdPersonAuto; private static ConfigEntry<int> thirdPersonAutoDistance; private static ConfigEntry<int> automaticReturnDelay; private static ConfigEntry<int> headBobStrength; internal static bool Enabled => enabled.Value; internal static float FieldOfView => fieldOfView.Value; internal static float FirstPersonFieldOfViewBonus => firstPersonFieldOfViewBonus.Value; internal static KeyboardShortcut ToggleShortcut => toggleShortcut.Value; internal static KeyboardShortcut ToggleThirdPersonAutoShortcut => toggleThirdPersonAutoShortcut.Value; internal static bool ThirdPersonAuto => thirdPersonAuto.Value; internal static int ThirdPersonAutoDistance => thirdPersonAutoDistance.Value; internal static int AutomaticReturnDelay => automaticReturnDelay.Value; internal static int HeadBobStrength => headBobStrength.Value; internal static void Initialize(ConfigFile config) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Expected O, but got Unknown enabled = config.Bind<bool>("Camera", "FirstPersonEnabled", false, "Whether first-person view is enabled at minimum camera zoom."); fieldOfView = config.Bind<float>("Camera", "FieldOfView", 65f, new ConfigDescription("Field of view shared by first-person, third-person, and free-fly cameras.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(65f, 120f), Array.Empty<object>())); firstPersonFieldOfViewBonus = config.Bind<float>("First Person", "FirstPersonFieldOfViewBonus", 15f, new ConfigDescription("Additional field of view applied only in first person.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); toggleShortcut = config.Bind<KeyboardShortcut>("First Person", "ToggleShortcut", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Shortcut used to enable or disable automatic first-person view.\n\nExamples: Mouse2 for the middle mouse button.\n\nMouse3/Mouse4 for the Forward/Back side button.\n\nSpace + LeftControl for Left Ctrl + Space.\n\nhttps://docs.unity3d.com/ScriptReference/KeyCode.html"); toggleThirdPersonAutoShortcut = config.Bind<KeyboardShortcut>("Third Person - Auto", "ToggleThirdPersonAutoShortcut", new KeyboardShortcut((KeyCode)287, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Shortcut used to enable or disable automatic third person during actions."); thirdPersonAuto = config.Bind<bool>("Third Person - Auto", "ThirdPersonAuto", false, "Whether actions such as attacking, blocking, chopping, mining, or building temporarily move the camera to third person."); thirdPersonAutoDistance = config.Bind<int>("Third Person - Auto", "ThirdPersonAutoDistance", 3, new ConfigDescription("Camera distance in meters while attacking or blocking.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); automaticReturnDelay = config.Bind<int>("Third Person - Auto", "AutomaticReturnDelay", 3, new ConfigDescription("ThirdPersonAuto delay before returning to first person after an action.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); headBobStrength = config.Bind<int>("First Person", "HeadBobStrength", 2, new ConfigDescription("First-person head bob strength. Set to 0 to disable head bob.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), Array.Empty<object>())); SetFieldOfView(fieldOfView.Value); } internal static void SetEnabled(bool value) { enabled.Value = value; ConfigWatcher.IgnoreCurrentFileVersion(); } internal static void SetThirdPersonAuto(bool value) { thirdPersonAuto.Value = value; ConfigWatcher.IgnoreCurrentFileVersion(); } internal static void SetFieldOfView(float value) { fieldOfView.Value = Math.Max(65f, Math.Min(value, 120f)); ConfigWatcher.IgnoreCurrentFileVersion(); } internal static void RestoreDefaults(ConfigFile config) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; try { enabled.Value = false; fieldOfView.Value = 65f; firstPersonFieldOfViewBonus.Value = 15f; toggleShortcut.Value = new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()); toggleThirdPersonAutoShortcut.Value = new KeyboardShortcut((KeyCode)287, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }); thirdPersonAuto.Value = false; thirdPersonAutoDistance.Value = 3; automaticReturnDelay.Value = 3; headBobStrength.Value = 2; } finally { config.SaveOnConfigSet = saveOnConfigSet; } config.Save(); ConfigWatcher.IgnoreCurrentFileVersion(); } } [BepInPlugin("Landoria.FirstPerson", "Landoria.FirstPerson", "1.0.14")] public sealed class Plugin : BaseUnityPlugin { private const string PluginGuid = "Landoria.FirstPerson"; private const string PluginName = "Landoria.FirstPerson"; private const string PluginVersion = "1.0.14"; private Harmony _harmony; private void Awake() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown ((BaseUnityPlugin)this).Logger.LogInfo((object)$"AssemblyVersion: {((object)this).GetType().Assembly.GetName().Version}."); _harmony = new Harmony("Landoria.FirstPerson"); _harmony.PatchAll(); Preference.Initialize(((BaseUnityPlugin)this).Config); ConfigWatcher.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger, "First Person", delegate { Preference.RestoreDefaults(((BaseUnityPlugin)this).Config); }, delegate { Mode.SetEnabled(Preference.Enabled); Mode.ApplyConfiguredFieldOfView(GameCamera.instance); }); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Landoria.FirstPerson 1.0.14 is loaded."); } private void Update() { ConfigWatcher.Update(); } private void OnDestroy() { ConfigWatcher.Dispose(); Mode.Reset(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Landoria.FirstPerson 1.0.14 is unloaded."); } } internal static class Shortcut { private static bool thirdPersonAutoActive; private static bool actionReturnCancelled; private static float actionThirdPersonEndTime; private static float expectedCameraDistance; internal static void Update(ref float cameraDistance) { //IL_000e: 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) UpdateActionCamera(ref cameraDistance); if (CanToggle()) { if (IsShortcutDown(Preference.ToggleThirdPersonAutoShortcut)) { ToggleThirdPersonAuto(ref cameraDistance); } else if (IsShortcutDown(Preference.ToggleShortcut)) { ToggleShortcut(); } } } internal static void PrepareDistanceObservation(float cameraDistance) { expectedCameraDistance = cameraDistance; } internal static void ObserveCameraDistance(ref float cameraDistance) { if (thirdPersonAutoActive) { bool num = cameraDistance > expectedCameraDistance + Mathf.Epsilon; bool flag = cameraDistance < expectedCameraDistance - Mathf.Epsilon; if (flag) { cameraDistance = 0f; } if (num || flag) { thirdPersonAutoActive = false; actionReturnCancelled = true; actionThirdPersonEndTime = 0f; } } } private static void ToggleShortcut() { thirdPersonAutoActive = false; actionReturnCancelled = false; actionThirdPersonEndTime = 0f; bool enabled = !Mode.Enabled; Mode.SetEnabled(enabled); Preference.SetEnabled(enabled); ShowState(enabled); } private static void ToggleThirdPersonAuto(ref float cameraDistance) { bool flag = !Preference.ThirdPersonAuto; Preference.SetThirdPersonAuto(flag); UpdateActionCamera(ref cameraDistance); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, flag ? "Third person auto enabled" : "Third person auto disabled", 0, (Sprite)null, false); } } private static void UpdateActionCamera(ref float cameraDistance) { if (!Preference.ThirdPersonAuto || !Mode.Enabled) { if (thirdPersonAutoActive) { cameraDistance = 0f; thirdPersonAutoActive = false; actionThirdPersonEndTime = 0f; } return; } Player localPlayer = Player.m_localPlayer; int num; if (Object.op_Implicit((Object)(object)localPlayer)) { if (!((Character)localPlayer).InAttack()) { num = (((Character)localPlayer).IsBlocking() ? 1 : 0); if (num == 0) { goto IL_0052; } } else { num = 1; } goto IL_0058; } num = 0; goto IL_0052; IL_0058: if (num != 0 && !actionReturnCancelled && (thirdPersonAutoActive || Mode.IsFirstPersonDistance(cameraDistance))) { if (!thirdPersonAutoActive) { cameraDistance = Preference.ThirdPersonAutoDistance; } thirdPersonAutoActive = true; actionThirdPersonEndTime = Time.unscaledTime + (float)Preference.AutomaticReturnDelay; } else if (thirdPersonAutoActive && Time.unscaledTime >= actionThirdPersonEndTime) { cameraDistance = 0f; thirdPersonAutoActive = false; actionThirdPersonEndTime = 0f; } return; IL_0052: actionReturnCancelled = false; goto IL_0058; } internal static void Reset() { thirdPersonAutoActive = false; actionReturnCancelled = false; actionThirdPersonEndTime = 0f; expectedCameraDistance = 0f; } private static bool CanToggle() { Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead() && !((Character)localPlayer).InCutscene() && !GameCamera.InFreeFly() && !Console.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible() && !StoreGui.IsVisible() && !Minimap.IsOpen() && !Hud.IsPieceSelectionVisible() && !Hud.InRadial()) { if (!((Object)(object)Chat.instance == (Object)null)) { return !Chat.instance.HasFocus(); } return true; } return false; } private static bool IsShortcutDown(KeyboardShortcut shortcut) { //IL_0002: 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_002a: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, true)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if (!ZInput.GetKey(modifier, true)) { return false; } } return true; } private static void ShowState(bool enabled) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, enabled ? "First person enabled" : "First person disabled", 0, (Sprite)null, false); } } } internal static class ViewController { private const float BackwardOffset = 0.4f; internal static void Apply(GameCamera camera, Player player) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) if (Object.op_Implicit((Object)(object)camera) && Object.op_Implicit((Object)(object)player) && !((Character)player).IsAttached() && !((Character)player).InCutscene()) { Quaternion rotation = ((Component)camera).transform.rotation; Vector3 forward = ((Component)camera).transform.forward; Vector3 val = Vector3.ProjectOnPlane(forward, Vector3.up); if (!Menu.IsVisible() && ((Vector3)(ref val)).sqrMagnitude > Mathf.Epsilon) { ((Character)player).SetLookDir(forward, 0f); ((Component)player).transform.rotation = Quaternion.LookRotation(val, Vector3.up); } Transform transform = ((Component)camera).transform; transform.position -= forward * 0.4f; ((Component)camera).transform.rotation = rotation; } } } internal static class VegetationController { private const string CameraCullProperty = "_CamCull"; private static readonly Dictionary<Material, float> CameraCullValues = new Dictionary<Material, float>(); internal static void Apply() { Material[] array = Resources.FindObjectsOfTypeAll<Material>(); for (int i = 0; i < array.Length; i++) { Apply(array[i]); } } internal static void Apply(GameObject root) { if (!Mode.Active || !Object.op_Implicit((Object)(object)root)) { return; } Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Material[] sharedMaterials = componentsInChildren[i].sharedMaterials; for (int j = 0; j < sharedMaterials.Length; j++) { Apply(sharedMaterials[j]); } } } internal static void Restore() { foreach (KeyValuePair<Material, float> cameraCullValue in CameraCullValues) { if (Object.op_Implicit((Object)(object)cameraCullValue.Key)) { cameraCullValue.Key.SetFloat("_CamCull", cameraCullValue.Value); } } CameraCullValues.Clear(); } private static void Apply(Material material) { if (Object.op_Implicit((Object)(object)material) && material.HasProperty("_CamCull") && !CameraCullValues.ContainsKey(material)) { float value = material.GetFloat("_CamCull"); CameraCullValues.Add(material, value); material.SetFloat("_CamCull", 0f); } } } internal static class VisibilityController { private static readonly HashSet<Renderer> HiddenRenderers = new HashSet<Renderer>(); private static readonly Dictionary<Animator, AnimatorCullingMode> AnimatorModes = new Dictionary<Animator, AnimatorCullingMode>(); private static Player hiddenPlayer; private static Player equippedPlayer; private static GameObject leftHandItem; private static GameObject rightHandItem; internal static void TrackHeldItems(Player player, GameObject leftItem, GameObject rightItem) { equippedPlayer = player; leftHandItem = leftItem; rightHandItem = rightItem; if (Object.op_Implicit((Object)(object)player) && (Object)(object)player == (Object)(object)hiddenPlayer) { HideCurrentVisuals(); } } internal static void SetHidden(Player player, bool hidden) { if (!hidden || !Object.op_Implicit((Object)(object)player)) { Restore(); } else if ((Object)(object)hiddenPlayer != (Object)(object)player) { Restore(); hiddenPlayer = player; HideCurrentVisuals(); } } internal static void Restore() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) foreach (Renderer hiddenRenderer in HiddenRenderers) { if (Object.op_Implicit((Object)(object)hiddenRenderer)) { hiddenRenderer.forceRenderingOff = false; } } foreach (KeyValuePair<Animator, AnimatorCullingMode> animatorMode in AnimatorModes) { if (Object.op_Implicit((Object)(object)animatorMode.Key)) { animatorMode.Key.cullingMode = animatorMode.Value; } } HiddenRenderers.Clear(); AnimatorModes.Clear(); hiddenPlayer = null; } private static void HideCurrentVisuals() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = ((Component)hiddenPlayer).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val) && !val.forceRenderingOff) { val.forceRenderingOff = true; HiddenRenderers.Add(val); } } Animator[] componentsInChildren2 = ((Component)hiddenPlayer).GetComponentsInChildren<Animator>(true); foreach (Animator val2 in componentsInChildren2) { if (Object.op_Implicit((Object)(object)val2) && !AnimatorModes.ContainsKey(val2)) { AnimatorModes.Add(val2, val2.cullingMode); val2.cullingMode = (AnimatorCullingMode)0; } } if ((Object)(object)hiddenPlayer == (Object)(object)equippedPlayer) { ShowHeldItem(leftHandItem); ShowHeldItem(rightHandItem); } } private static void ShowHeldItem(GameObject item) { if (!Object.op_Implicit((Object)(object)item)) { return; } Renderer[] componentsInChildren = item.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val) && HiddenRenderers.Remove(val)) { val.forceRenderingOff = false; } } } } }