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 Unswayed v1.0.2
Unswayed.dll
Decompiled 2 days agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using Unswayed.Configuration; using Unswayed.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Unswayed")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2+0da1cae3147c46d2bc627672b90c5f98e3fbfcff")] [assembly: AssemblyProduct("Unswayed")] [assembly: AssemblyTitle("Unswayed")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 Unswayed { [BepInPlugin("djc.valheim.unswayed", "Unswayed", "1.0.2")] public sealed class UnswayedPlugin : BaseUnityPlugin { public const string PluginGUID = "djc.valheim.unswayed"; public const string PluginName = "Unswayed"; public const string PluginVersion = "1.0.2"; private Harmony? _harmony; public static UnswayedPlugin? Instance { get; private set; } private void Awake() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) Instance = this; PluginConfig.BindConfig(((BaseUnityPlugin)this).Config); _harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "djc.valheim.unswayed"); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1} initialized. Bobbing Suppression: {2} (Damping: {3:F2}), Dungeon Ergonomics: {4}, Shake Scale: {5:F2}. Hotkey: [{6}]", "Unswayed", "1.0.2", PluginConfig.EnableBobSuppression.Value, PluginConfig.VerticalDamping.Value, PluginConfig.EnableDungeonErgonomics.Value, PluginConfig.CameraShakeScale.Value, PluginConfig.ToggleHotkey.Value)); } private void Update() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (PluginConfig.ToggleHotkey != null && Input.GetKeyDown(PluginConfig.ToggleHotkey.Value)) { StabilizerManager.ToggleStabilization(out string message); ((BaseUnityPlugin)this).Logger.LogInfo((object)message); if ((Object)(object)Console.instance != (Object)null) { ((Terminal)Console.instance).AddString(message); } } } private void OnDestroy() { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } Instance = null; } } } namespace Unswayed.Patches { [HarmonyPatch(typeof(GameCamera))] public static class CameraStabilizerPatches { [HarmonyPostfix] [HarmonyPatch("GetCameraBaseOffset")] public static void GetCameraBaseOffsetPostfix(GameCamera __instance, Player player, ref Vector3 __result) { //IL_0061: 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_0088: 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) if (!PluginConfig.IsModEnabled.Value || !PluginConfig.EnableBobSuppression.Value || ((Character)player).InBed() || ((Character)player).IsAttached() || ((Character)player).IsSitting()) { return; } switch (PluginConfig.Mode.Value) { case SuppressionMode.RunningOnly: if (!((Character)player).IsRunning() && !((Character)player).IsWalking()) { return; } break; case SuppressionMode.DungeonsOnly: if (!StabilizerManager.IsInDungeonOrTightSpace(__instance)) { return; } break; } Vector3 val = Vector3.up * PluginConfig.StabilizedEyeHeight.Value; float num = Mathf.Clamp01(PluginConfig.VerticalDamping.Value); __result = Vector3.Lerp(__result, val, num); } [HarmonyPostfix] [HarmonyPatch("GetCameraPosition")] public static void GetCameraPositionPostfix(GameCamera __instance, float dt, ref Vector3 pos, ref Quaternion rot) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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) //IL_00cd: 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) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.IsModEnabled.Value) { return; } Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return; } Vector3 val = (Object.op_Implicit((Object)(object)((Character)localPlayer).m_eye) ? ((Character)localPlayer).m_eye.position : (((Component)localPlayer).transform.position + Vector3.up * 1.6f)); float num = (StabilizerManager.LastCameraDistance = Vector3.Distance(val, pos)); bool flag = (StabilizerManager.IsTightSpace = num < PluginConfig.DungeonProximityThreshold.Value && num > 0.01f); if (!PluginConfig.EnableDungeonErgonomics.Value) { return; } if (PluginConfig.EnableMinDistanceClamp.Value && num < PluginConfig.MinCameraDistance.Value && num > 0.05f) { Vector3 val2 = pos - val; Vector3 val3 = ((Vector3)(ref val2)).normalized; if (val3 == Vector3.zero) { val3 = -((Component)localPlayer).transform.forward; } pos = val + val3 * PluginConfig.MinCameraDistance.Value; num = PluginConfig.MinCameraDistance.Value; } if (flag && PluginConfig.EnableCryptShoulderLift.Value) { float value = PluginConfig.DungeonProximityThreshold.Value; float num3 = Mathf.Clamp01(1f - num / value) * PluginConfig.ShoulderLiftAmount.Value; pos += Vector3.up * num3; } if (PluginConfig.DisableShipTilt.Value && __instance.m_shipCameraTilt) { Vector3 eulerAngles = ((Quaternion)(ref rot)).eulerAngles; eulerAngles.z = 0f; rot = Quaternion.Euler(eulerAngles); } } [HarmonyPostfix] [HarmonyPatch("UpdateFOV")] public static void UpdateFOVPostfix(GameCamera __instance) { if (!PluginConfig.IsModEnabled.Value || !PluginConfig.EnableDungeonFovBoost.Value) { StabilizerManager.ResetFov(__instance); } else if (StabilizerManager.IsTightSpace && PluginConfig.DungeonFovBoost.Value > 0.1f) { float value = PluginConfig.DungeonFovBoost.Value; StabilizerManager.CurrentFovOffset = Mathf.MoveTowards(StabilizerManager.CurrentFovOffset, value, Time.deltaTime * 45f); Camera camera = __instance.m_camera; camera.fieldOfView += StabilizerManager.CurrentFovOffset; } else if (StabilizerManager.CurrentFovOffset > 0.01f) { StabilizerManager.CurrentFovOffset = Mathf.MoveTowards(StabilizerManager.CurrentFovOffset, 0f, Time.deltaTime * 30f); Camera camera2 = __instance.m_camera; camera2.fieldOfView += StabilizerManager.CurrentFovOffset; } } [HarmonyPrefix] [HarmonyPatch("UpdateCameraShake")] public static void UpdateCameraShakePrefix(GameCamera __instance) { if (PluginConfig.IsModEnabled.Value) { float num = Mathf.Clamp01(PluginConfig.CameraShakeScale.Value); if (num <= 0.001f) { __instance.m_shakeIntensity = 0f; } else if (num < 0.999f) { __instance.m_shakeIntensity *= num; } } } } } namespace Unswayed.Core { public static class StabilizerManager { public static float LastCameraDistance { get; set; } = 4f; public static bool IsTightSpace { get; set; } = false; public static float OriginalBaseFov { get; set; } = 65f; public static float CurrentFovOffset { get; set; } = 0f; public static bool IsInDungeonOrTightSpace(GameCamera? camera) { if ((Object)(object)camera == (Object)null) { return false; } if (!IsTightSpace) { return camera.m_distance < PluginConfig.DungeonProximityThreshold.Value; } return true; } public static void ToggleStabilization(out string message) { PluginConfig.IsModEnabled.Value = !PluginConfig.IsModEnabled.Value; message = "[Unswayed] Camera stabilization is now " + (PluginConfig.IsModEnabled.Value ? "ENABLED" : "DISABLED") + "."; } public static void ResetFov(GameCamera camera) { if ((Object)(object)camera != (Object)null && (Object)(object)camera.m_camera != (Object)null && CurrentFovOffset > 0.01f) { camera.m_camera.fieldOfView = OriginalBaseFov; CurrentFovOffset = 0f; } } } } namespace Unswayed.Configuration { public enum SuppressionMode { Always, RunningOnly, DungeonsOnly } public static class PluginConfig { public static ConfigEntry<bool> IsModEnabled; public static ConfigEntry<KeyCode> ToggleHotkey; public static ConfigEntry<bool> EnableBobSuppression; public static ConfigEntry<SuppressionMode> Mode; public static ConfigEntry<float> StabilizedEyeHeight; public static ConfigEntry<float> VerticalDamping; public static ConfigEntry<bool> EnableDungeonErgonomics; public static ConfigEntry<float> DungeonProximityThreshold; public static ConfigEntry<bool> EnableMinDistanceClamp; public static ConfigEntry<float> MinCameraDistance; public static ConfigEntry<bool> EnableCryptShoulderLift; public static ConfigEntry<float> ShoulderLiftAmount; public static ConfigEntry<bool> EnableDungeonFovBoost; public static ConfigEntry<float> DungeonFovBoost; public static ConfigEntry<float> CameraShakeScale; public static ConfigEntry<bool> DisableShipTilt; public static void BindConfig(ConfigFile config) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Expected O, but got Unknown //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Expected O, but got Unknown //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Expected O, but got Unknown IsModEnabled = config.Bind<bool>("1 - General", "Enabled", true, "Master toggle for Unswayed camera stabilization."); ToggleHotkey = config.Bind<KeyCode>("1 - General", "ToggleHotkey", (KeyCode)288, "In-game hotkey to quickly toggle camera stabilization on/off."); EnableBobSuppression = config.Bind<bool>("2 - Head-Bob Suppression", "EnableBobSuppression", true, "Decouples the camera base offset from the animated head bone, completely eliminating the 1.0 vertical running bounce."); Mode = config.Bind<SuppressionMode>("2 - Head-Bob Suppression", "SuppressionMode", SuppressionMode.Always, "When to suppress head-bobbing: Always, RunningOnly (only when sprinting/running), or DungeonsOnly."); StabilizedEyeHeight = config.Bind<float>("2 - Head-Bob Suppression", "StabilizedEyeHeight", 1.65f, new ConfigDescription("Stable vertical eye pivot height relative to player root transform.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1.2f, 2.2f), Array.Empty<object>())); VerticalDamping = config.Bind<float>("2 - Head-Bob Suppression", "VerticalDamping", 1f, new ConfigDescription("Amount of vertical bobbing suppression (1.0 = completely stable horizon, 0.5 = 50% reduced bounce, 0.0 = vanilla bounce).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); EnableDungeonErgonomics = config.Bind<bool>("3 - Dungeon & Crypt Ergonomics", "EnableDungeonErgonomics", true, "Enables adaptive camera behavior when compressed in tight corridors, burial crypts, and sunken crypts."); DungeonProximityThreshold = config.Bind<float>("3 - Dungeon & Crypt Ergonomics", "DungeonProximityThreshold", 1.8f, new ConfigDescription("Camera distance threshold (meters) below which dungeon/tight-space adaptations activate.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), Array.Empty<object>())); EnableMinDistanceClamp = config.Bind<bool>("3 - Dungeon & Crypt Ergonomics", "EnableMinDistanceClamp", true, "Prevents the camera collision raycast from crushing point-blank into the player's skull."); MinCameraDistance = config.Bind<float>("3 - Dungeon & Crypt Ergonomics", "MinCameraDistance", 0.9f, new ConfigDescription("Minimum camera distance in tight spaces to prevent the Viking mesh from filling the entire screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 2f), Array.Empty<object>())); EnableCryptShoulderLift = config.Bind<bool>("3 - Dungeon & Crypt Ergonomics", "EnableCryptShoulderLift", true, "Gently elevates the camera over the Viking's shoulders when camera distance drops in tight crypts, preserving forward visibility."); ShoulderLiftAmount = config.Bind<float>("3 - Dungeon & Crypt Ergonomics", "ShoulderLiftAmount", 0.35f, new ConfigDescription("Maximum vertical shoulder lift in tight spaces.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 0.8f), Array.Empty<object>())); EnableDungeonFovBoost = config.Bind<bool>("3 - Dungeon & Crypt Ergonomics", "EnableDungeonFovBoost", true, "Dynamically expands FOV when navigating tight crypts to widen peripheral vision and reduce nausea."); DungeonFovBoost = config.Bind<float>("3 - Dungeon & Crypt Ergonomics", "DungeonFovBoost", 15f, new ConfigDescription("Additional FOV degrees added in tight crypt spaces (e.g. 65° -> 80°).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>())); CameraShakeScale = config.Bind<float>("4 - Motion Sickness Toggles", "CameraShakeScale", 0f, new ConfigDescription("Global camera shake multiplier (0.0 = completely off, 0.2 = subtle rumble, 1.0 = vanilla full shake).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); DisableShipTilt = config.Bind<bool>("4 - Motion Sickness Toggles", "DisableShipTilt", false, "Suppresses camera roll/tilt when sailing on boats (prevents seasickness)."); } } } namespace Unswayed.Commands { [HarmonyPatch(typeof(Terminal), "InitTerminal")] public static class UnswayedCommand { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; internal void <AddTerminalCommands>b__0_0(ConsoleEventArgs args) { if (args.Length < 2) { PrintStatus(args.Context); return; } switch (args[1].ToLowerInvariant()) { case "toggle": { StabilizerManager.ToggleStabilization(out string message); args.Context.AddString(message); break; } case "status": PrintStatus(args.Context); break; case "height": { if (args.Length >= 3 && float.TryParse(args[2], out var result2)) { PluginConfig.StabilizedEyeHeight.Value = Mathf.Clamp(result2, 1.2f, 2.2f); args.Context.AddString($"[Unswayed] Stabilized eye height set to: {PluginConfig.StabilizedEyeHeight.Value:F2}m"); } else { args.Context.AddString($"[Unswayed] Current height: {PluginConfig.StabilizedEyeHeight.Value:F2}m. Usage: unswayed height <1.2 - 2.2>"); } break; } case "damping": { if (args.Length >= 3 && float.TryParse(args[2], out var result3)) { PluginConfig.VerticalDamping.Value = Mathf.Clamp01(result3); args.Context.AddString($"[Unswayed] Vertical damping set to: {PluginConfig.VerticalDamping.Value:F2} (1.0 = stable, 0.0 = vanilla)"); } else { args.Context.AddString($"[Unswayed] Current damping: {PluginConfig.VerticalDamping.Value:F2}. Usage: unswayed damping <0.0 - 1.0>"); } break; } case "shake": { if (args.Length >= 3 && float.TryParse(args[2], out var result)) { PluginConfig.CameraShakeScale.Value = Mathf.Clamp01(result); args.Context.AddString($"[Unswayed] Camera shake scale set to: {PluginConfig.CameraShakeScale.Value:F2}"); } else { args.Context.AddString($"[Unswayed] Current shake scale: {PluginConfig.CameraShakeScale.Value:F2}. Usage: unswayed shake <0.0 - 1.0>"); } break; } default: args.Context.AddString("[Unswayed] Available commands: toggle, status, height <m>, damping <0-1>, shake <0-1>"); break; } } } [HarmonyPostfix] public static void AddTerminalCommands() { //IL_0033: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if (args.Length < 2) { PrintStatus(args.Context); } else { switch (args[1].ToLowerInvariant()) { case "toggle": { StabilizerManager.ToggleStabilization(out string message); args.Context.AddString(message); break; } case "status": PrintStatus(args.Context); break; case "height": { if (args.Length >= 3 && float.TryParse(args[2], out var result2)) { PluginConfig.StabilizedEyeHeight.Value = Mathf.Clamp(result2, 1.2f, 2.2f); args.Context.AddString($"[Unswayed] Stabilized eye height set to: {PluginConfig.StabilizedEyeHeight.Value:F2}m"); } else { args.Context.AddString($"[Unswayed] Current height: {PluginConfig.StabilizedEyeHeight.Value:F2}m. Usage: unswayed height <1.2 - 2.2>"); } break; } case "damping": { if (args.Length >= 3 && float.TryParse(args[2], out var result3)) { PluginConfig.VerticalDamping.Value = Mathf.Clamp01(result3); args.Context.AddString($"[Unswayed] Vertical damping set to: {PluginConfig.VerticalDamping.Value:F2} (1.0 = stable, 0.0 = vanilla)"); } else { args.Context.AddString($"[Unswayed] Current damping: {PluginConfig.VerticalDamping.Value:F2}. Usage: unswayed damping <0.0 - 1.0>"); } break; } case "shake": { if (args.Length >= 3 && float.TryParse(args[2], out var result)) { PluginConfig.CameraShakeScale.Value = Mathf.Clamp01(result); args.Context.AddString($"[Unswayed] Camera shake scale set to: {PluginConfig.CameraShakeScale.Value:F2}"); } else { args.Context.AddString($"[Unswayed] Current shake scale: {PluginConfig.CameraShakeScale.Value:F2}. Usage: unswayed shake <0.0 - 1.0>"); } break; } default: args.Context.AddString("[Unswayed] Available commands: toggle, status, height <m>, damping <0-1>, shake <0-1>"); break; } } }; <>c.<>9__0_0 = val; obj = (object)val; } new ConsoleCommand("unswayed", "Manage Unswayed camera stabilization (toggle, status, height, damping)", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static void PrintStatus(Terminal terminal) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) terminal.AddString("=== [Unswayed Camera Stabilizer v1.0.0] ==="); terminal.AddString($" Enabled: {PluginConfig.IsModEnabled.Value} (Hotkey: [{PluginConfig.ToggleHotkey.Value}])"); terminal.AddString($" Mode: {PluginConfig.Mode.Value} | Damping: {PluginConfig.VerticalDamping.Value:F2} | Eye Height: {PluginConfig.StabilizedEyeHeight.Value:F2}m"); terminal.AddString($" Dungeon Ergonomics: {PluginConfig.EnableDungeonErgonomics.Value} (MinDist: {PluginConfig.MinCameraDistance.Value:F2}m, ShoulderLift: +{PluginConfig.ShoulderLiftAmount.Value:F2}m, FOV Boost: +{PluginConfig.DungeonFovBoost.Value:F0}°)"); terminal.AddString($" Camera Shake Scale: {PluginConfig.CameraShakeScale.Value:F2} | Disable Ship Tilt: {PluginConfig.DisableShipTilt.Value}"); terminal.AddString($" Live Camera Distance: {StabilizerManager.LastCameraDistance:F2}m (Tight Space: {StabilizerManager.IsTightSpace})"); } } }