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 Operator v1.0.0
BepInEx/plugins/Operator/Operator.dll
Decompiled 6 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.IO.Pipes; using System.Linq; using System.Net; using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Dawn; using Dawn.Utils; using Dissonance; using Dissonance.Audio.Capture; using Dissonance.Audio.Playback; using Dusk; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using Microsoft.CodeAnalysis; using NAudio.Wave; using Operator.Cassette; using Operator.Compat; using Operator.Input; using Operator.NetcodePatcher; using Operator.Recording; using Operator.Recording.Voice; using TMPro; using Unity.Collections; using Unity.Netcode; using Unity.Profiling; using Unity.Profiling.LowLevel.Unsafe; using UnityEngine; using UnityEngine.Animations; using UnityEngine.Animations.Rigging; using UnityEngine.Audio; using UnityEngine.Events; using UnityEngine.Experimental.Animations; using UnityEngine.InputSystem; using UnityEngine.Playables; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; using UnityEngine.UI; using UnityEngine.Video; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.github.teamxiaolan.dawnlib.dusk")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("DunGen")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")] [assembly: IgnoresAccessChecksTo("Unity.XR.Management")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Operator")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Camcorder to record, rewatch and sell cassettes.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+5d7783104509cbd3d67e0ce6230828f2e46499a9")] [assembly: AssemblyProduct("Operator")] [assembly: AssemblyTitle("Operator")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] 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 Operator { internal static class AssetsLoader { internal class KnownAssets : AssetBundleLoader<KnownAssets> { [LoadFromBundle("VideoCameraItem")] public Item CameraItem { get; private set; } public KnownAssets(AssetBundle bundle) : base(bundle) { } } private static AssetBundle? _bundle; private static KnownAssets? _known; private static Material? _ledRedLightMaterial; private static Material? _ledBlackLightMaterial; private static Material? _ledPauseLightMaterial; private static Material? _ledIrLightMaterial; private static readonly int EmissiveColorId = Shader.PropertyToID("_EmissiveColor"); private static readonly Dictionary<string, AudioClip?> _dialogueBleeps = new Dictionary<string, AudioClip>(); private static AudioClip? _cameraHandlingClip; private static bool _cameraHandlingAttempted; private static AudioClip? _zoomClip; private static bool _zoomAttempted; private static AudioClip? _zoomReversedClip; private static AudioClip? _recordingRunClip; private static bool _recordingRunAttempted; private static AudioClip? _buttonPressClip; private static bool _buttonPressAttempted; private static AudioClip? _buttonHoldClip; private static bool _buttonHoldAttempted; private static AudioClip? _cassetteEjectClip; private static bool _cassetteEjectAttempted; private static AudioClip? _nightVisionOffClip; private static bool _nightVisionOffAttempted; private static AudioClip[]? _lensBreakClips; private static bool _lensBreakAttempted; private static AnimationClip? _holdClip; private static bool _holdClipAttempted; private static AnimationClip? _holdLeftClip; private static bool _holdLeftClipAttempted; private static readonly Random StaticNoiseRng = new Random(); public static Material? LedRedLightMaterial { get { if ((Object)(object)_ledRedLightMaterial == (Object)null) { _ledRedLightMaterial = AssetsLoader.LoadOptionalAsset<Material>("RedLight"); } return _ledRedLightMaterial; } } public static Material? LedBlackLightMaterial { get { if ((Object)(object)_ledBlackLightMaterial == (Object)null) { _ledBlackLightMaterial = AssetsLoader.LoadOptionalAsset<Material>("BlackLight"); } return _ledBlackLightMaterial; } } public static Material? LedPauseLightMaterial { get { if ((Object)(object)_ledPauseLightMaterial == (Object)null) { _ledPauseLightMaterial = AssetsLoader.LoadOptionalAsset<Material>("PauseMaterial"); } return _ledPauseLightMaterial; } } public static Material? LedIrLightMaterial { get { //IL_0025: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_ledIrLightMaterial != (Object)null) { return _ledIrLightMaterial; } Material ledBlackLightMaterial = LedBlackLightMaterial; if ((Object)(object)ledBlackLightMaterial == (Object)null) { return null; } _ledIrLightMaterial = new Material(ledBlackLightMaterial) { name = "OperatorIrLight", hideFlags = (HideFlags)61 }; if (_ledIrLightMaterial.HasProperty(EmissiveColorId)) { _ledIrLightMaterial.SetColor(EmissiveColorId, Constants.Parts.IrLampColor); } return _ledIrLightMaterial; } } public static AnimationClip? HoldClip { get { if ((Object)(object)_holdClip != (Object)null || _holdClipAttempted) { return _holdClip; } _holdClipAttempted = true; _holdClip = AssetsLoader.LoadOptionalAsset<AnimationClip>("CameraHoldPose"); if ((Object)(object)_holdClip == (Object)null) { Plugin.Log.LogWarning((object)"Could not find camera hold animation."); } return _holdClip; } } public static AnimationClip? HoldLeftClip { get { if ((Object)(object)_holdLeftClip != (Object)null || _holdLeftClipAttempted) { return _holdLeftClip; } _holdLeftClipAttempted = true; _holdLeftClip = AssetsLoader.LoadOptionalAsset<AnimationClip>("CameraHoldLeft"); if ((Object)(object)_holdLeftClip == (Object)null) { Plugin.Log.LogWarning((object)"Could not find left hand hold animation. The left hand stays off the screen."); } return _holdLeftClip; } } public static Item? CameraItem => _known?.CameraItem; public static AudioClip? GetDialogueBleepClip(string clipName) { if (_dialogueBleeps.TryGetValue(clipName, out AudioClip value)) { return value; } AudioClip val = FindDialogueBleep(HUDManager.Instance, clipName); if ((Object)(object)val == (Object)null) { HUDManager[] array = Resources.FindObjectsOfTypeAll<HUDManager>(); foreach (HUDManager hud in array) { val = FindDialogueBleep(hud, clipName); if ((Object)(object)val != (Object)null) { break; } } } _dialogueBleeps[clipName] = val; return val; } private static AudioClip? FindDialogueBleep(HUDManager? hud, string clipName) { if ((Object)(object)hud == (Object)null || hud.dialogueBleeps == null) { return null; } AudioClip[] dialogueBleeps = hud.dialogueBleeps; foreach (AudioClip val in dialogueBleeps) { if ((Object)(object)val != (Object)null && ((Object)val).name == clipName) { return val; } } return null; } public static AudioClip? GetCameraHandlingClip() { if ((Object)(object)_cameraHandlingClip != (Object)null) { return _cameraHandlingClip; } if (_cameraHandlingAttempted) { return null; } _cameraHandlingAttempted = true; _cameraHandlingClip = AssetsLoader.LoadOptionalAsset<AudioClip>("camerahandling"); return _cameraHandlingClip; } public static AudioClip? GetZoomClip() { if ((Object)(object)_zoomClip != (Object)null) { return _zoomClip; } if (_zoomAttempted) { return null; } _zoomAttempted = true; _zoomClip = AssetsLoader.LoadOptionalAsset<AudioClip>("zoom"); return _zoomClip; } public static void WarmAudioClips() { Stopwatch stopwatch = Stopwatch.StartNew(); WarmClip("recording run", GetRecordingRunClip); WarmClip("button press", GetButtonPressClip); WarmClip("button hold", GetButtonHoldClip); WarmClip("camera handling", GetCameraHandlingClip); WarmClip("zoom", GetZoomClip); WarmClip("cassette eject", GetCassetteEjectClip); WarmClip("night vision off", GetNightVisionOffClip); } private static void WarmClip(string name, Func<AudioClip?> load) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 try { Stopwatch stopwatch = Stopwatch.StartNew(); AudioClip val = load(); if ((Object)(object)val != (Object)null && (int)val.loadState != 2) { val.LoadAudioData(); } } catch (Exception ex) { Plugin.Log.LogDebug((object)("Could not warm " + name + " clip, " + ex.Message)); } } public static AudioClip? GetRecordingRunClip() { if ((Object)(object)_recordingRunClip != (Object)null) { return _recordingRunClip; } if (_recordingRunAttempted) { return null; } _recordingRunAttempted = true; _recordingRunClip = AssetsLoader.LoadOptionalAsset<AudioClip>("filmcamerarunning"); return _recordingRunClip; } public static AudioClip? GetButtonPressClip() { if ((Object)(object)_buttonPressClip != (Object)null) { return _buttonPressClip; } if (_buttonPressAttempted) { return null; } _buttonPressAttempted = true; _buttonPressClip = AssetsLoader.LoadOptionalAsset<AudioClip>("buttonpress"); return _buttonPressClip; } public static AudioClip? GetButtonHoldClip() { if ((Object)(object)_buttonHoldClip != (Object)null) { return _buttonHoldClip; } if (_buttonHoldAttempted) { return null; } _buttonHoldAttempted = true; _buttonHoldClip = AssetsLoader.LoadOptionalAsset<AudioClip>("buttonhold"); return _buttonHoldClip; } public static AudioClip? GetCassetteEjectClip() { if ((Object)(object)_cassetteEjectClip != (Object)null) { return _cassetteEjectClip; } if (_cassetteEjectAttempted) { return null; } _cassetteEjectAttempted = true; _cassetteEjectClip = AssetsLoader.LoadOptionalAsset<AudioClip>("cassetteeject"); return _cassetteEjectClip; } public static AudioClip? GetNightVisionOffClip() { if ((Object)(object)_nightVisionOffClip != (Object)null) { return _nightVisionOffClip; } if (_nightVisionOffAttempted) { return null; } _nightVisionOffAttempted = true; _nightVisionOffClip = AssetsLoader.LoadOptionalAsset<AudioClip>("shutterclick"); return _nightVisionOffClip; } public static AudioClip? GetLensBreakClip() { if (!_lensBreakAttempted) { _lensBreakAttempted = true; List<AudioClip> list = new List<AudioClip>(); string[] lensBreakClipNames = Constants.Assets.LensBreakClipNames; foreach (string assetName in lensBreakClipNames) { AudioClip val = AssetsLoader.LoadOptionalAsset<AudioClip>(assetName); if ((Object)(object)val != (Object)null) { list.Add(val); } } _lensBreakClips = list.ToArray(); } if (_lensBreakClips == null || _lensBreakClips.Length == 0) { return null; } if (_lensBreakClips.Length == 1) { return _lensBreakClips[0]; } return _lensBreakClips[StaticNoiseRng.Next(_lensBreakClips.Length)]; } public static AudioClip? GetZoomReversedClip() { if ((Object)(object)_zoomReversedClip != (Object)null) { return _zoomReversedClip; } AudioClip zoomClip = GetZoomClip(); if ((Object)(object)zoomClip == (Object)null) { return null; } _zoomReversedClip = CreateReversedClip(zoomClip, ((Object)zoomClip).name + "_reversed"); return _zoomReversedClip; } private static AudioClip? CreateReversedClip(AudioClip src, string name) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 try { int samples = src.samples; int channels = src.channels; if (samples <= 0 || channels <= 0) { return null; } if ((int)src.loadState != 2) { src.LoadAudioData(); } float[] array = new float[samples * channels]; if (!src.GetData(array, 0)) { return null; } int num = 0; int num2 = samples - 1; while (num < num2) { for (int i = 0; i < channels; i++) { int num3 = num * channels + i; int num4 = num2 * channels + i; ref float reference = ref array[num3]; ref float reference2 = ref array[num4]; float num5 = array[num4]; float num6 = array[num3]; reference = num5; reference2 = num6; } num++; num2--; } AudioClip val = AudioClip.Create(name, samples, channels, src.frequency, false); val.SetData(array, 0); return val; } catch (Exception ex) { Plugin.Log.LogDebug((object)("Could not reverse '" + name + "' clip: " + ex.Message)); return null; } } public static bool TryLoadBundle() { if ((Object)(object)_bundle != (Object)null) { return true; } string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = Path.Combine(directoryName, "operatorassets"); if (!File.Exists(text)) { Plugin.Log.LogError((object)("Could not find asset bundle at '" + text + "'. Camera is disabled.")); return false; } try { _bundle = AssetBundle.LoadFromFile(text); } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to load asset bundle: " + ex.Message)); return false; } if ((Object)(object)_bundle == (Object)null) { Plugin.Log.LogError((object)"Failed to load asset bundle. Camera is disabled."); return false; } _known = new KnownAssets(_bundle); Plugin.Log.LogInfo((object)"Loaded asset bundle."); return true; } public static T? LoadOptionalAsset<T>(string assetName) where T : Object { if ((Object)(object)_bundle == (Object)null || string.IsNullOrWhiteSpace(assetName)) { return default(T); } return _bundle.LoadAsset<T>(assetName); } } public enum EncoderChoice { Auto, Nvidia, Intel, Amd, Cpu } public enum RecordingResolutionPreset { High_860x520, Medium_640x360, Low_426x240, UltraLow_256x144 } public enum RecordedMicCharacter { Off, Casual, Real, Aggressive } public enum RecordingAudioBitratePreset { Kbps16 = 16, Kbps24 = 24, Kbps32 = 32, Kbps48 = 48, Kbps64 = 64, Kbps96 = 96, Kbps128 = 128, Kbps160 = 160, Kbps192 = 192, Kbps256 = 256, Kbps320 = 320 } public enum OcclusionEffectStyle { PlainBlackFade, VignetteClosing, VignetteSmear } public enum CameraFilterMode { Point, Bilinear } public enum CameraOverlayStyle { Off, Minimal, Classic, Vhs, Pro } public enum CameraFocusMode { Off, Auto, Manual } public enum FeedExposureMode { Off, Casual, Real } public enum DeathRecordingBehavior { DeadManRoll, KeepFilming } public enum FeedRenderQuality { Quality, Performance } public enum LensRepair { Never, EachQuota, EachOrbit } internal static class VideoCameraConfig { private static bool _bountyOrphansCleared; public static ConfigEntry<int> StoreCost { get; private set; } public static ConfigEntry<string> TerminalHelpKeyword { get; private set; } public static ConfigEntry<float> MinFov { get; private set; } public static ConfigEntry<float> MaxFov { get; private set; } public static ConfigEntry<float> ZoomSpeed { get; private set; } public static ConfigEntry<float> IdleBatteryDrain { get; private set; } public static ConfigEntry<float> BobIntensity { get; private set; } public static ConfigEntry<float> ScreenEmissionIntensity { get; private set; } public static ConfigEntry<RecordingResolutionPreset> RenderResolution { get; private set; } public static ConfigEntry<CameraFilterMode> RenderFilterMode { get; private set; } public static ConfigEntry<int> RenderFps { get; private set; } public static ConfigEntry<FeedRenderQuality> RenderQuality { get; private set; } public static ConfigEntry<bool> WeatherPerspective { get; private set; } public static ConfigEntry<CameraOverlayStyle> Overlay { get; private set; } public static ConfigEntry<CameraFocusMode> FocusMode { get; private set; } public static ConfigEntry<FeedExposureMode> FeedExposure { get; private set; } public static ConfigEntry<OcclusionEffectStyle> OcclusionStyle { get; private set; } public static ConfigEntry<float> EffectStrength { get; private set; } public static ConfigEntry<float> FearResponse { get; private set; } public static ConfigEntry<float> Vignette { get; private set; } public static ConfigEntry<float> BarrelDistortion { get; private set; } public static ConfigEntry<float> ChromaticAberration { get; private set; } public static ConfigEntry<float> LensDust { get; private set; } public static ConfigEntry<float> VeilingGlare { get; private set; } public static ConfigEntry<float> FocusBreathing { get; private set; } public static ConfigEntry<float> RainIntensity { get; private set; } public static ConfigEntry<float> Grain { get; private set; } public static ConfigEntry<float> Scanlines { get; private set; } public static ConfigEntry<float> TrackingGlitch { get; private set; } public static ConfigEntry<float> ColdDesaturation { get; private set; } public static ConfigEntry<float> ExposurePump { get; private set; } public static ConfigEntry<float> WhiteBalanceDrift { get; private set; } public static ConfigEntry<bool> CrackOnLens { get; private set; } public static ConfigEntry<int> CrackDamageThreshold { get; private set; } public static ConfigEntry<int> CrackMaxStages { get; private set; } public static ConfigEntry<LensRepair> LensRepair { get; private set; } public static ConfigEntry<bool> RecordingEnabled { get; private set; } public static ConfigEntry<RecordingResolutionPreset> RecordingResolution { get; private set; } public static ConfigEntry<int> RecordingFps { get; private set; } public static ConfigEntry<int> RecordingCrf { get; private set; } public static ConfigEntry<int> MaxMinutes { get; private set; } public static ConfigEntry<int> MaxQueuedVideoFrames { get; private set; } public static ConfigEntry<DeathRecordingBehavior> DeathBehavior { get; private set; } public static ConfigEntry<bool> KeepUnsavedPerLobby { get; private set; } public static ConfigEntry<string> OutputDirectoryOverride { get; private set; } public static ConfigEntry<EncoderChoice> Encoder { get; private set; } public static ConfigEntry<string> FfmpegExePath { get; private set; } public static ConfigEntry<bool> RecordAudio { get; private set; } public static ConfigEntry<RecordingAudioBitratePreset> AudioBitrateKbps { get; private set; } public static ConfigEntry<RecordedMicCharacter> MicCharacter { get; private set; } public static ConfigEntry<bool> MicEnvironmentEffects { get; private set; } public static ConfigEntry<float> MicReverbAmount { get; private set; } public static ConfigEntry<float> MicVolume { get; private set; } public static ConfigEntry<float> EchoStrength { get; private set; } public static ConfigEntry<float> VoiceRange { get; private set; } public static ConfigEntry<float> DeathStaticFadeSeconds { get; private set; } public static ConfigEntry<bool> BroadcastRecordingsToClients { get; private set; } public static ConfigEntry<bool> KeepReceivedClips { get; private set; } public static ConfigEntry<bool> TerminalCoWatch { get; private set; } public static ConfigEntry<bool> TransferAudioFromSpeaker { get; private set; } public static ConfigEntry<bool> TelevisionCassetteWatching { get; private set; } public static ConfigEntry<float> TelevisionScreenLightIntensity { get; private set; } public static ConfigEntry<float> MonitorScreenLightIntensity { get; private set; } public static ConfigEntry<int> BlankCassettesPerOrbit { get; private set; } public static ConfigEntry<bool> BlanksPerShip { get; private set; } public static ConfigEntry<int> FlatBaseValue { get; private set; } public static ConfigEntry<int> DeadBodyPenalty { get; private set; } public static ConfigEntry<float> MinSecondsForBounty { get; private set; } public static ConfigEntry<string> WorthlessMoonsForced { get; private set; } public static ConfigEntry<string> WorthlessMoonsExcluded { get; private set; } public static ConfigEntry<bool> WorthlessOrbitFootage { get; private set; } private static (int Width, int Height) ResolutionFromPreset(RecordingResolutionPreset preset) { return preset switch { RecordingResolutionPreset.UltraLow_256x144 => (Width: 256, Height: 144), RecordingResolutionPreset.Low_426x240 => (Width: 426, Height: 240), RecordingResolutionPreset.Medium_640x360 => (Width: 640, Height: 360), RecordingResolutionPreset.High_860x520 => (Width: 860, Height: 520), _ => (Width: 640, Height: 360), }; } public static (int Width, int Height) GetRecordingSize() { return ResolutionFromPreset(RecordingResolution.Value); } public static (int Width, int Height) GetRenderSize() { return ResolutionFromPreset(RenderResolution.Value); } public static (int Width, int Height) GetReadbackSize(int captureWidth, int captureHeight) { var (num, num2) = GetRecordingSize(); if (num * num2 >= captureWidth * captureHeight) { return (Width: captureWidth, Height: captureHeight); } return (Width: num, Height: num2); } public static int GetAudioBitrate() { int value = (int)AudioBitrateKbps.Value; return Mathf.Clamp(value, 16, 320); } public static float GetEffect(ConfigEntry<float> slider) { return Mathf.Max(0f, slider.Value) * Mathf.Clamp01(EffectStrength.Value); } public static int GetRecordingFps() { return Mathf.Clamp(RecordingFps.Value, 12, 60); } public static void Initialize(ConfigFile config) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Expected O, but got Unknown //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Expected O, but got Unknown //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Expected O, but got Unknown //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Expected O, but got Unknown //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Expected O, but got Unknown //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Expected O, but got Unknown //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Expected O, but got Unknown //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Expected O, but got Unknown //IL_03f3: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Expected O, but got Unknown //IL_042b: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Expected O, but got Unknown //IL_0463: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Expected O, but got Unknown //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04a5: Expected O, but got Unknown //IL_04d3: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Expected O, but got Unknown //IL_050b: Unknown result type (might be due to invalid IL or missing references) //IL_0515: Expected O, but got Unknown //IL_0543: Unknown result type (might be due to invalid IL or missing references) //IL_054d: Expected O, but got Unknown //IL_057b: Unknown result type (might be due to invalid IL or missing references) //IL_0585: Expected O, but got Unknown //IL_05b3: Unknown result type (might be due to invalid IL or missing references) //IL_05bd: Expected O, but got Unknown //IL_05eb: Unknown result type (might be due to invalid IL or missing references) //IL_05f5: Expected O, but got Unknown //IL_0634: Unknown result type (might be due to invalid IL or missing references) //IL_063e: Expected O, but got Unknown //IL_0660: Unknown result type (might be due to invalid IL or missing references) //IL_066a: Expected O, but got Unknown //IL_06e0: Unknown result type (might be due to invalid IL or missing references) //IL_06ea: Expected O, but got Unknown //IL_070f: Unknown result type (might be due to invalid IL or missing references) //IL_0719: Expected O, but got Unknown //IL_073d: Unknown result type (might be due to invalid IL or missing references) //IL_0747: Expected O, but got Unknown //IL_076f: Unknown result type (might be due to invalid IL or missing references) //IL_0779: Expected O, but got Unknown //IL_08cc: Unknown result type (might be due to invalid IL or missing references) //IL_08d6: Expected O, but got Unknown //IL_0904: Unknown result type (might be due to invalid IL or missing references) //IL_090e: Expected O, but got Unknown //IL_093c: Unknown result type (might be due to invalid IL or missing references) //IL_0946: Expected O, but got Unknown //IL_0974: Unknown result type (might be due to invalid IL or missing references) //IL_097e: Expected O, but got Unknown //IL_09ac: Unknown result type (might be due to invalid IL or missing references) //IL_09b6: Expected O, but got Unknown //IL_0a6b: Unknown result type (might be due to invalid IL or missing references) //IL_0a75: Expected O, but got Unknown //IL_0aa3: Unknown result type (might be due to invalid IL or missing references) //IL_0aad: Expected O, but got Unknown //IL_0ad0: Unknown result type (might be due to invalid IL or missing references) //IL_0ada: Expected O, but got Unknown //IL_0af6: Unknown result type (might be due to invalid IL or missing references) //IL_0b00: Expected O, but got Unknown //IL_0b23: Unknown result type (might be due to invalid IL or missing references) //IL_0b2d: Expected O, but got Unknown //IL_0b51: Unknown result type (might be due to invalid IL or missing references) //IL_0b5b: Expected O, but got Unknown //IL_0b89: Unknown result type (might be due to invalid IL or missing references) //IL_0b93: Expected O, but got Unknown config.SaveOnConfigSet = false; StoreCost = config.Bind<int>("1. General", "StoreCost", 260, new ConfigDescription("Camcorder price in store.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 9999), Array.Empty<object>())); TerminalHelpKeyword = config.Bind<string>("1. General", "TerminalHelpKeyword", "ohelp", "Word to type in terminal to list every command of this mod."); MinFov = config.Bind<float>("2. Camera", "MinFov", 25f, new ConfigDescription("How far camera can zoom in.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 70f), Array.Empty<object>())); MaxFov = config.Bind<float>("2. Camera", "MaxFov", 75f, new ConfigDescription("How far camera can zoom out.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 90f), Array.Empty<object>())); ZoomSpeed = config.Bind<float>("2. Camera", "ZoomSpeed", 40f, new ConfigDescription("Zooming speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 120f), Array.Empty<object>())); IdleBatteryDrain = config.Bind<float>("2. Camera", "IdleBatteryDrain", 0.4f, new ConfigDescription("Battery drain while Camcorder is on but not recording.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); BobIntensity = config.Bind<float>("2. Camera", "BobIntensity", 1.25f, new ConfigDescription("How much camera sways as player with camera walks.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); ScreenEmissionIntensity = config.Bind<float>("2. Camera", "ScreenEmissionIntensity", 3f, new ConfigDescription("How brightly camera screen emits.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); RenderResolution = config.Bind<RecordingResolutionPreset>("3. Feed", "RenderResolution", RecordingResolutionPreset.Medium_640x360, "Resolution camera renders its own screen at."); RenderFilterMode = config.Bind<CameraFilterMode>("3. Feed", "FilterMode", CameraFilterMode.Point, "How camera image is sampled onto screen. 'Point' is pixelated and matches an old tape. 'Bilinear' is smooth."); RenderFps = config.Bind<int>("3. Feed", "RenderFps", 30, new ConfigDescription("How many times per second camera screen rerenders, lower saves CPU. Recordings are unaffected.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(24, 60), Array.Empty<object>())); RenderQuality = config.Bind<FeedRenderQuality>("3. Feed", "RenderQuality", FeedRenderQuality.Quality, "'Quality' graphics like in cyberpunk. 'Performance' renders the feed without shadows or volumetric fog and with lower detail models, about half its cost outdoors. 'Quality' keeps all of that."); WeatherPerspective = config.Bind<bool>("3. Feed", "WeatherPerspective", true, "Show weather from where camera is instead of where players are. Turn this off if modded weather looks wrong on screen."); Overlay = config.Bind<CameraOverlayStyle>("3. Feed", "Overlay", CameraOverlayStyle.Pro, "Camcorder style screen display. 'Off' is clear screen. 'Minimal' shows REC and battery. 'Classic' adds timecode and frame. 'Vhs' is retro look. 'Pro' is full Handycam style."); FocusMode = config.Bind<CameraFocusMode>("3. Feed", "FocusMode", CameraFocusMode.Auto, "'Off' keeps everything always sharp. 'Auto' blurs and refocuses on its own. 'Manul' lets you pull focus yourself with Focus Near/Far keys using reticle on screen to see when youre sharp."); FeedExposure = config.Bind<FeedExposureMode>("3. Feed", "Exposure", FeedExposureMode.Real, "Simulates camcorders exposure catching up when lighting changes suddenly. 'Casual' is gentle lag that never lowers visibility. 'Real' does it properly and can briefly wash out or go dark."); OcclusionStyle = config.Bind<OcclusionEffectStyle>("3. Feed", "OcclusionStyle", OcclusionEffectStyle.VignetteSmear, "How feed reacts when camera is pressed against objects so you cannot see through walls. 'PlainBlackFade' just dims to black. 'VignetteClosing' closes edges inward and blurs as it darkens. 'VignetteSmear' adds directional smear at close range."); EffectStrength = config.Bind<float>("4. Effects", "EffectStrength", 1f, new ConfigDescription("Master value over every effect below. Lens cracks, night vision, exposure lag and screen display are separate and stay on.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); FearResponse = config.Bind<float>("4. Effects", "FearResponse", 1f, new ConfigDescription("How hard camera reacts to held camera mans fear.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); Vignette = config.Bind<float>("4. Effects", "Vignette", 1f, new ConfigDescription("How dark corners of frame darken.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); BarrelDistortion = config.Bind<float>("4. Effects", "BarrelDistortion", 1f, new ConfigDescription("How much lens distorts image outward at edges.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); ChromaticAberration = config.Bind<float>("4. Effects", "ChromaticAberration", 1f, new ConfigDescription("Colour fringing that grows toward edges of frame where lens fails to focus red and blue on same spot.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); LensDust = config.Bind<float>("4. Effects", "LensDust", 0.5f, new ConfigDescription("Dust and smears on front element.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); VeilingGlare = config.Bind<float>("4. Effects", "VeilingGlare", 0.5f, new ConfigDescription("Stray light scattering off lens elements into haze around bright sources.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); FocusBreathing = config.Bind<float>("4. Effects", "FocusBreathing", 1f, new ConfigDescription("Slight zoom that happens as lens racks focus.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); RainIntensity = config.Bind<float>("4. Effects", "RainIntensity", 1f, new ConfigDescription("How heavily rain beads on lens while outside in rainy or stormy weather.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); Grain = config.Bind<float>("4. Effects", "Grain", 1f, new ConfigDescription("Tape grain over the whole image.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); Scanlines = config.Bind<float>("4. Effects", "Scanlines", 1f, new ConfigDescription("Darkened alternating rows, look of an interlaced tape.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); TrackingGlitch = config.Bind<float>("4. Effects", "TrackingGlitch", 1f, new ConfigDescription("Tape tracking errors that tear across frame when fear jumps suddenly.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); ColdDesaturation = config.Bind<float>("4. Effects", "ColdDesaturation", 1f, new ConfigDescription("Colour draining toward cold grey as fear rises.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); ExposurePump = config.Bind<float>("4. Effects", "ExposurePump", 1f, new ConfigDescription("Exposure hunting up and down when player is frightened.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); WhiteBalanceDrift = config.Bind<float>("4. Effects", "WhiteBalanceDrift", 1f, new ConfigDescription("White balance sliding warmer or cooler with fear.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); CrackOnLens = config.Bind<bool>("4. Effects", "CrackOnLens", true, "Camera lens cracks when you take damage or drop camera from height."); CrackDamageThreshold = config.Bind<int>("4. Effects", "CrackDamageThreshold", 20, new ConfigDescription("How much health you must lose to add crack stage.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); CrackMaxStages = config.Bind<int>("4. Effects", "CrackMaxStages", 2, new ConfigDescription("Max lens crack stages.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 3), Array.Empty<object>())); LensRepair = config.Bind<LensRepair>("4. Effects", "LensRepair", Operator.LensRepair.EachQuota, "When cracked camera lens is repaired. 'EachOrbit' repairs every time ship leaves moon and returns to orbit. 'EachQuota' repairs only when new profit quota begins. 'Never' leaves cracks permanently."); RecordingEnabled = config.Bind<bool>("5. Recording", "Enabled", true, "Write recordings to output directory while camera is powered on. Turning this off leaves camera working as viewfinder that records nothing."); RecordingResolution = config.Bind<RecordingResolutionPreset>("5. Recording", "Resolution", RecordingResolutionPreset.Low_426x240, "Resolution of recorded MP4."); RecordingFps = config.Bind<int>("5. Recording", "Fps", 24, new ConfigDescription("Framerate of recorded MP4. 60 is smooth and increases the size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(12, 60), Array.Empty<object>())); RecordingCrf = config.Bind<int>("5. Recording", "Crf", 23, new ConfigDescription("Recording quality. Lower is better quality and bigger file. 16 is near lossless, 32 is visibly blocky.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(16, 32), Array.Empty<object>())); MaxMinutes = config.Bind<int>("5. Recording", "MaxMinutes", 10, new ConfigDescription("Recording stops on its own after this many minutes of filming.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60), Array.Empty<object>())); MaxQueuedVideoFrames = config.Bind<int>("5. Recording", "MaxQueuedVideoFrames", 96, new ConfigDescription("INTENDED FOR TESTING ONLY. Leave this at 96 unless you are doing stuff.\n\nMaximum video frames buffered between capture pump and ffmpeg. ffmpeg takes few seconds to start reading and anything captured past this buffer is replaced by repeated frame, so lowering it brings back stutter at start of every recording. Raising it trades RAM for headroom on slower machines.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(48, 600), Array.Empty<object>())); DeathBehavior = config.Bind<DeathRecordingBehavior>("5. Recording", "DeathBehavior", DeathRecordingBehavior.KeepFilming, "What camera does when operator dies while filming. 'KeepFilming' keeps recording with static hiss. 'DeadManRoll' rolls static instead."); KeepUnsavedPerLobby = config.Bind<bool>("5. Recording", "KeepUnsavedPerLobby", true, "Keep finished recordings per lobby under Recordings/Lobbies/<save file>/ and only move one into main Recordings folder when you save that cassette. Cassette that no longer exists is cleaned up automatically. Turn this off to write every finished recording straight to main Recordings folder and keep it."); OutputDirectoryOverride = config.Bind<string>("5. Recording", "OutputDirectoryOverride", "", "Path for output folder. Leave empty to use %USERPROFILE%\\AppData\\LocalLow\\ZeekerssRBLX\\Lethal Company\\Recordings\\."); Encoder = config.Bind<EncoderChoice>("5. Recording", "Encoder", EncoderChoice.Auto, "Auto tries NVIDIA, Intel and AMD, then the CPU (x264). Cpu always works, about 6% of one core at 426x240. Under Proton (Linux, Steam Deck) Auto uses the CPU."); Encoder.SettingChanged += delegate { VideoEncoder.Restart(); }; FfmpegExePath = config.Bind<string>("5. Recording", "FfmpegExePath", "", "Path to an existing ffmpeg.exe. Leave empty to auto download and cache pinned build under BepInEx/cache/ffmpeg/."); RecordAudio = config.Bind<bool>("6. Audio", "RecordAudio", true, "Capture game audio onto recording. Turning this off saves disk space and makes MP4 silent hill."); AudioBitrateKbps = config.Bind<RecordingAudioBitratePreset>("6. Audio", "AudioBitrateKbps", RecordingAudioBitratePreset.Kbps64, "AAC audio bitrate. 32 and below sound obviously compressed, 192 and above are wasted on a camcorder mix."); MicCharacter = config.Bind<RecordedMicCharacter>("6. Audio", "MicCharacter", RecordedMicCharacter.Casual, "Run recording through camcorder microphone. It band limits sound, adds tape hiss and rides level so a quiet room swells up and a loud noise ducks everything for moment. 'Off' records clean mix."); MicEnvironmentEffects = config.Bind<bool>("6. Audio", "MicEnvironmentEffects", true, "Run your recorded microphone through games real environmental voice filters so it matches what other players hear."); MicReverbAmount = config.Bind<float>("6. Audio", "MicReverbAmount", 0.5f, new ConfigDescription("How much room players own recorded microphone picks up so your own voice sits in world instead of on top of it. Only affects players own mic.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); MicVolume = config.Bind<float>("6. Audio", "MicVolume", 1f, new ConfigDescription("Volume of your own voice on tape. 1 is your mic as is, 2 twice as loud, 0 leaves it out.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 4f), Array.Empty<object>())); EchoStrength = config.Bind<float>("6. Audio", "EchoStrength", 1f, new ConfigDescription("How much room recorded voice is heard in. Raise it for wetter, more cavernous tape, lower it for drier one.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); VoiceRange = config.Bind<float>("6. Audio", "VoiceRange", 50f, new ConfigDescription("Meters at which recorded voices fade out, yours too when camera is set down. 50 is game's own range.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 150f), Array.Empty<object>())); DeathStaticFadeSeconds = config.Bind<float>("6. Audio", "DeathStaticFadeSeconds", 8f, new ConfigDescription("How long static takes to fade out after player dies with camera and camera keeps recording.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>())); BroadcastRecordingsToClients = config.Bind<bool>("7. Sharing", "BroadcastRecordingsToClients", true, "[Client side] After recording finishes send MP4 to everyone else so they can watch it. They get saved under ZeekerssRBLX/Lethal Company/Recordings/Received/. This is read on whoever did recording so host cannot turn it off for everyone."); KeepReceivedClips = config.Bind<bool>("7. Sharing", "KeepReceivedClips", false, "Keep other players recordings that were sent to you, under Recordings/Received/ so you can rewatch them anytime. If false, each is marked for deletion once no longer needed. Use 'save <id>' in terminal to keep permanently."); TerminalCoWatch = config.Bind<bool>("7. Sharing", "TerminalCoWatch", true, "When anyone plays cassette in terminal/TV, mirror it to every players terminal so whole lobby sees and hears same recording."); TransferAudioFromSpeaker = config.Bind<bool>("7. Sharing", "TransferAudioFromSpeaker", true, "Play transferred recording through ship speaker. If false, sound comes from monitor itself."); TelevisionCassetteWatching = config.Bind<bool>("7. Sharing", "TelevisionCassetteWatching", true, "Add cassette deck on top of ship Television. Insert cassette to play its recording on TV screen for whole lobby."); TelevisionScreenLightIntensity = config.Bind<float>("7. Sharing", "TelevisionScreenLightIntensity", 1.6f, new ConfigDescription("How hard playing recording drives Television light.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); MonitorScreenLightIntensity = config.Bind<float>("7. Sharing", "MonitorScreenLightIntensity", 1.6f, new ConfigDescription("How hard transferred recording drives ship monitor light.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); BlankCassettesPerOrbit = config.Bind<int>("8. Economy", "BlankCassettesPerOrbit", 1, new ConfigDescription("Blank cassettes restocked each time the ship reaches orbit. Counts for the whole ship when 'BlanksPerShip' is true, otherwise each camera gets this many.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); BlanksPerShip = config.Bind<bool>("8. Economy", "BlanksPerShip", true, new ConfigDescription("Every camera takes from one shared stock of 'BlankCassettesPerOrbit' blanks, so second camera does not mean more tapes.", (AcceptableValueBase)null, Array.Empty<object>())); FlatBaseValue = config.Bind<int>("8. Economy", "FlatBaseValue", 5, new ConfigDescription("Scrap value added to every cassette regardless of what is on it.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); DeadBodyPenalty = config.Bind<int>("8. Economy", "DeadBodyPenalty", 25, new ConfigDescription("Percent taken off the earned part of a tape for each dead crewmate filmed long enough to count (see 'MinSecondsForBounty'). Bodies already in the ship or being carried don't count. 'FlatBaseValue' is never reduced. 0 turns it off.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); MinSecondsForBounty = config.Bind<float>("8. Economy", "MinSecondsForBounty", 2f, new ConfigDescription("How long an individual enemy or dead body must spend on camera before any value is added for it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 15f), Array.Empty<object>())); WorthlessMoonsForced = config.Bind<string>("8. Economy", "WorthlessMoonsForced", "", "Extra moons whose cassettes is worth nothing, separated by commas, i.e. \"Assurance, Titan\". Cassettes from the Company is already worth nothing."); WorthlessMoonsExcluded = config.Bind<string>("8. Economy", "WorthlessMoonsExcluded", "", "Moons to keep paying for even though they look like the Company moons, separated by commas, i.e. \"Assurance, Titan\"."); WorthlessOrbitFootage = config.Bind<bool>("8. Economy", "WorthlessOrbitFootage", true, "Cassettes shot in orbit is worth nothing."); ClearOrphanedEntries(config); config.Save(); config.SaveOnConfigSet = true; LethalConfigCompat.Register(config); } private static Dictionary<ConfigDefinition, string>? GetOrphanedEntries(ConfigFile config) { return AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(config) as Dictionary<ConfigDefinition, string>; } private static int RemoveOrphans(Dictionary<ConfigDefinition, string> orphanedEntries, bool bountySection) { List<ConfigDefinition> list = new List<ConfigDefinition>(); foreach (ConfigDefinition key in orphanedEntries.Keys) { if (key.Section == "9. Bounties" == bountySection) { list.Add(key); } } foreach (ConfigDefinition item in list) { orphanedEntries.Remove(item); } return list.Count; } private static void ClearOrphanedEntries(ConfigFile config) { try { Dictionary<ConfigDefinition, string> orphanedEntries = GetOrphanedEntries(config); if (orphanedEntries != null && orphanedEntries.Count != 0) { int num = RemoveOrphans(orphanedEntries, bountySection: false); if (num > 0) { Plugin.Log.LogInfo((object)$"Cleared {num} settings that no longer exist."); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to clear obsolete settings: " + ex.Message)); } } internal static void ClearBountyOrphans(ConfigFile config) { if (_bountyOrphansCleared) { return; } _bountyOrphansCleared = true; try { Dictionary<ConfigDefinition, string> orphanedEntries = GetOrphanedEntries(config); if (orphanedEntries != null) { int num = RemoveOrphans(orphanedEntries, bountySection: true); if (num > 0) { Plugin.Log.LogInfo((object)$"Cleared {num} bounty entries for enemies that are no longer installed."); } config.Save(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to clear obsolete bounty entries: " + ex.Message)); } } } internal static class Constants { internal static class PluginMetadata { public const string ContentNamespace = "seeya"; public const string ItemKey = "video_camera"; public const string Description = "Camcorder to record, rewatch and sell cassettes."; } internal static class Assets { public const string BundleFileName = "operatorassets"; public const string ItemAssetName = "VideoCameraItem"; public const string HoldClipName = "CameraHoldPose"; public const string HoldLeftClipName = "CameraHoldLeft"; public const string NightVisionShaderName = "NightVision"; public const string MaterialRedLightName = "RedLight"; public const string MaterialBlackLightName = "BlackLight"; public const string MaterialPauseLightName = "PauseMaterial"; public const string PrefabScreenTextureName = "CamScreenTexture"; public const string PocketObjectName = "PocketHinge"; public const string PocketOpenAnimationName = "PocketOpen"; public const string PocketCloseAnimationName = "PocketClose"; public const string PocketEjectAnimationName = "PocketEject"; public const string ScreenShellObjectName = "ScreenGroup"; public const string ScreenShellAnimationName = "ScreenOpening"; public const string ScreenShellCloseAnimationName = "ScreenClosing"; public const string ScreenHingeObjectName = "ScreenHinge"; public const string ScreenRendererObjectName = "screenplane"; public const string ScreenLightObjectName = "ScreenLight"; public const string FilmObjectName = "FilmGroup"; public const string FilmSpinAnimationName = "FilmSpin"; public const string RedLightObjectName = "RedLight"; public const string RedLight2ObjectName = "RedLight2"; public const string RecordLampObjectName = "recordlamp"; public const string WebcamLampObjectName = "webcamlamp"; public const string TallyLampObjectName = "tallyFront"; public const string WebcamObjectName = "WebcamGroup"; public const string WebcamGlassObjectName = "webcamglass"; public const string WebcamOpenAnimationName = "WebcamOpen"; public const string WebcamCloseAnimationName = "WebcamClose"; public const string RecordButtonObjectName = "playbutton"; public const string FlipButtonObjectName = "flipbutton"; public const string NightVisionButtonObjectName = "nvbutton"; public const string ZoomInButtonObjectName = "zoombuttonplus"; public const string ZoomOutButtonObjectName = "zoombuttonminus"; public const string ButtonPressClipSuffix = "Press"; public const string ButtonDownClipSuffix = "Down"; public const string ButtonUpClipSuffix = "Up"; public const string EjectAnchorObjectName = "EjectAnchor"; public const string LensCoverObjectName = "LensCover"; public const string LensCoverOpenAnimationName = "LensCoverOpen"; public const string LensCoverCloseAnimationName = "LensCoverClose"; public const string FocusRingObjectName = "focusring"; public const string FocusWheelObjectName = "focuswheel"; public const string ZoomRingObjectName = "zoomring"; public const string NeedleObjectName = "NeedlePivot"; public const string IrLampObjectName = "irlamp"; public const string CoilObjectName = "dcCoil"; public const string ButtonOnClipSuffix = "On"; public const string ButtonOffClipSuffix = "Off"; public static readonly string[] TapeReelObjectNames = new string[2] { "reeltape1", "reeltape2" }; public const string CameraHandlingClipName = "camerahandling"; public const string ZoomClipName = "zoom"; public const string RecordingRunClipName = "filmcamerarunning"; public const string ButtonPressClipName = "buttonpress"; public const string ButtonHoldClipName = "buttonhold"; public const string CassetteEjectClipName = "cassetteeject"; public const string NightVisionOffClipName = "shutterclick"; public static readonly string[] LensBreakClipNames = new string[2] { "lensbreak", "lensbreak2" }; public const string RecordingStartClipName = "ComputerBeep3"; public const string RecordingPauseClipName = "ComputerBeep1"; public const string RecordingResumeClipName = "ComputerBeep6"; } internal static class Network { public const int NetcodeVersion = 11; public const string NetcodeVersionField = "opnet:"; } internal static class ClipTransfer { public const int ChunkSize = 32768; public const int MaxChunks = 65536; public const int MaxResendChunks = 256; public const int MaxActiveClips = 16; public const int MaxEvictWaits = 3; public const int SendRate = 10; public const int FlowWindowChunks = 8; public const int AckIntervalChunks = 4; public const float FlowPollInterval = 0.05f; public const float FlowStallTimeout = 30f; public const float SenderCacheTime = 180f; public const float RetryDelay = 2f; public const int MaxRetries = 8; public const float RecoveryTimeout = 120f; public const float MinRecoveryRate = 3f; } internal static class ConfigRanges { public const int StoreCostMin = 20; public const int StoreCostMax = 9999; public const float CameraMinFovMin = 10f; public const float CameraMinFovMax = 70f; public const float CameraMaxFovMin = 10f; public const float CameraMaxFovMax = 90f; public const float CameraZoomSpeedMin = 5f; public const float CameraZoomSpeedMax = 120f; public const float CameraBobIntensityMin = 0f; public const float CameraBobIntensityMax = 3f; public const float ScreenEmissionMin = 0f; public const float ScreenEmissionMax = 10f; public const float IdleBatteryDrainMin = 0f; public const float IdleBatteryDrainMax = 2f; public const int FeedRenderFpsMin = 24; public const int FeedRenderFpsMax = 60; public const int FpsMin = 12; public const int FpsMax = 60; public const int CrfMin = 16; public const int CrfMax = 32; public const int AudioBitrateMin = 16; public const int AudioBitrateMax = 320; public const int MaxMinutesMin = 1; public const int MaxMinutesMax = 60; public const int MaxQueuedFramesMin = 48; public const int MaxQueuedFramesMax = 600; public const int FlatBaseValueMin = 0; public const int FlatBaseValueMax = 100; public const int DeadBodyPenaltyMin = 0; public const int DeadBodyPenaltyMax = 100; public const float MinBountyTimeMin = 0f; public const float MinBountyTimeMax = 15f; public const int CassettesPerOrbitMin = 1; public const int CassettesPerOrbitMax = 10; public const float TelevisionLightMin = 0f; public const float TelevisionLightMax = 5f; public const float MonitorLightMin = 0f; public const float MonitorLightMax = 5f; } internal static class Parts { public const float RingSweep = 79f; public const float FocusNearDiopter = 1.25f; public const float FocusWheelRatio = 3.48f; public const float NeedleEmptyAngle = 50f; public const float NeedleFullAngle = -50f; public const float NeedleSpeed = 3f; public const float NeedleTremble = 0.9f; public const float NeedleTrembleRate = 17f; public const float CoilStiffness = 140f; public const float CoilDamping = 5f; public const float CoilMaxOffset = 0.012f; public static readonly Color IrLampColor = new Color(0.5f, 0f, 0f, 1f); } internal static class Camera { public const float ShellOpenDelay = 0.5f; public const float SlotOpenDelay = 0.3f; public const int ClipMatchSteps = 12; public const int ClipMatchPasses = 3; public const float ClipMatchAngleWeight = 0.0002f; public const float ShellCloseCut = 0.63f; public const float DefaultFov = 65f; public const float HeldNearBlurEnd = 0.2f; public const float ScreenAspect = 1.7777778f; public static readonly Color ScreenOffAlbedo = new Color(0.02f, 0.023f, 0.021f, 1f); public static readonly Color ScreenLitBaseTint = new Color(0.03f, 0.03f, 0.03f, 1f); public const float HoldBlendTime = 0.25f; public const float HoldReleaseTime = 0.06f; public const ushort HoldSortingOrder = 500; public const ushort HoldLeftSortingOrder = 501; public const float HoldLeftReleaseTime = 0.12f; public const float HoldSteadiness = 0.8f; public const float HoldSteadyFade = 0.15f; public const float HoldSteadyReach = 0.35f; public const float HoldRestRate = 0.2f; public const float HoldRestDelay = 0.5f; public const float HoldRestSpeed = 0.3f; public const float HoldRestHeight = -0.294f; public const float HoldRestDepth = 0.585f; public const float ScreenOpenAngle = 110f; public const int FloorYOffset = -90; public const float MaxEjectDistance = 8f; public const float PocketOpenSettle = 0.25f; public const float EjectLift = 0.06f; public const float EjectLiftTime = 0.1f; public const float EjectCrossfade = 0.06f; public static readonly Vector3 DecorTurn = new Vector3(0f, 180f, 0f); public const float EjectUpSpeed = 2.4f; public const float EjectClearance = 0.05f; public const float EjectDistance = 0.45f; public const float EjectSpread = 0.08f; public const float EjectProbeRadius = 0.08f; public const float EjectWallGap = 0.1f; public const float EjectSpin = 90f; public const float EjectSpinJitter = 30f; public const float EjectHop = 0.035f; public const float EjectHopTime = 0.12f; public const float EjectRock = 4f; public const float EjectRockTime = 0.2f; public const float EjectPinTimeout = 1f; public const float EjectPinDistance = 0.005f; public const float EjectPinAngle = 0.5f; } internal static class Battery { public const float DrainInterval = 0.25f; public const float IdleDrainMultiplier = 0.4f; public const float RecordDrainMultiplier = 0.4f; public const float CapacityScale = 2f; } internal static class Visual { public const int FeedRenderFps = 30; public const float FeedFarClipPlane = 300f; public const float FarScreenSize = 8f; public const float FarScreenRate = 4f; public const float HiddenFogMeanFreePath = 1000000f; public const string PreviewExcludeLayerNames = "ScanNode,LineOfSight,MapRadar,HelmetVisor,UI"; public const float WaterRescanInterval = 5f; public const float UnderwaterFade = 10f; public const float UnderwaterFadeFloor = 0.05f; public const float RemoteLensForward = 1.02f; public const float RemoteLensRight = 0.467f; public const float RemoteLensDown = 0.185f; public const float RemoteLensReach = 3f; public const float BarrelMax = 0.2f; public const int CamcorderIdleReleaseFrames = 120; public const float GlareThresholdCalm = 0.9f; public const float GlareThresholdAfraid = 0.9f; public const float GlareKnee = 0.1f; public const float GlareOverRange = 0f; public const float GlareHaloCalm = 0.2f; public const float GlareHaloAfraid = 0.3f; public const float GlareVeilCalm = 0.01f; public const float GlareVeilAfraid = 0.03f; public const float GlareSmearCalm = 0.05f; public const float GlareSmearAfraid = 0.1f; public const float GlareNearStep = 0.6f; public const float GlareMidStep = 1f; public const float GlareFarStep = 1f; public const float GlareSmearStep = 1f; public const float GlareSkipBelow = 0.02f; public const float ScreenGlowRange = 1.3f; public const float ScreenGlowSpotAngle = 150f; public const float ScreenGlowInnerSpot = 0.1f; public const float ScreenGlowWhite = 60f; public const float ScreenGlowFloor = 0.1f; public const float ScreenGlowDarkPeak = 0.0001f; public const float ScreenGlowOpenStart = 0.6f; public const float ScreenGlowSelfieScale = 0.5f; public const float ScreenGlowSelfieMax = 3f; public const float ScreenGlowSampleInterval = 0.04f; public static readonly Vector3 ScreenGlowOffset = new Vector3(0.01f, 0f, 0f); public static readonly Vector3 ScreenGlowTurn = new Vector3(0f, 90f, 0f); public const int ScreenGlowProbeSize = 64; public const float ScreenGlowResponseSpeed = 10f; public const int RawProbeSize = 16; public const float RawSampleInterval = 0.08f; public const float RawResponseSpeed = 6f; public const float LampIntensity = 0.1f; public const float LampRange = 0.02f; public static readonly Color LampColor = new Color(1f, 0.05f, 0.02f); public const string OcclusionLayerNames = "Default,Room,Terrain,Colliders,InteractableObject,DecalStickableSurface"; public const float OcclusionProbeRadius = 0.05f; public const float OcclusionSelfHitEpsilon = 0.02f; public const float OcclusionFadeDistance = 1f; public const float OcclusionNightVisionOnset = 0.5f; public const float OcclusionGrazeFloor = 0.15f; public const float OcclusionNightVisionSlew = 16f; public const float OcclusionNearPlaneEngage = 0.01f; public const float OcclusionNearPlaneRelease = 0.04f; public const float OcclusionDroppedReach = 0.78f; public const int OcclusionVignetteTextureSize = 128; public static readonly bool BobEnabled = true; public const float BobWalkFrequency = 5.5f; public const float BobRunFrequency = 8.5f; public const float BobWalkPitch = 1.2f; public const float BobRunPitch = 4f; public const float BobWalkRoll = 0.7f; public const float BobRunRoll = 2.4f; public const float WeatherScanInterval = 2f; public const float WeatherRetryDelay = 3f; public const float CoverCheckInterval = 0.75f; public const float CoverCheckDistance = 100f; public const float MeteorSpriteDistance = 380f; public const int WeatherCameraLayer = 31; } internal static class Exposure { public const float ApplyEpsilon = 0.01f; public const float RelaxSpeed = 2.5f; public const float MaxDeltaTime = 0.05f; public const float EvFloor = 0.0001f; public const float MaxSlewRate = 10f; public const float SettleTime = 0.5f; public const float RealTauRise = 0.55f; public const float RealTauFall = 0.45f; public const float RealDeadOver = 0.5f; public const float RealDeadUnder = 0.75f; public const float RealMaxOver = 2f; public const float RealMaxUnder = 2f; public const float CasualTauRise = 0.3f; public const float CasualTauFall = 0.25f; public const float CasualDeadOver = 0.75f; public const float CasualDeadUnder = 1f; public const float CasualMaxOver = 1f; public const float CasualMaxUnder = 1f; } internal static class Focus { public const float AutoFocusSpeed = 6f; public const float RackSpeed = 2.4f; public const float DarkRackMultiplier = 0.45f; public const float ReactionDelay = 0.22f; public const float RetargetThreshold = 0.18f; public const float DriftSpeed = 0.35f; public const float AreaOffset = 0.1f; public const float AreaSmoothing = 0.15f; public const float AreaRackSmoothing = 0.03f; public const float BlurFade = 0.4f; public const float HuntDuration = 0.9f; public const float HuntCycles = 2.2f; public const float HuntAmplitude = 0.55f; public const float ZoomSettleTime = 0.15f; public const float MinIdleHuntInterval = 20f; public const float MaxIdleHuntInterval = 50f; public const float DarkHuntTimeScale = 0.4f; public const float DarkLumaThreshold = 0.16f; public const float ManualRackSpeed = 1.4f; public const float ManualNearLimit = 0.3f; public const float ManualFarLimit = 120f; public const float BlurPerDiopter = 0.75f; public const float BlurStepMax = 0.9f; public const float ZoomBlurPower = 0.5f; public const float MaxZoomBlur = 4f; public const float BreathScale = 0.0022f; public const float BreathMax = 0.008f; public const float BreathResponse = 6f; } internal static class NightVision { public const float SwitchTime = 0.05f; public const float HoldTime = 0.3f; public const float SettleTime = 0.6f; public const float DisableDelay = 0.12f; public const float BloomStrength = 0.5f; public const float BandWidth = 0.3f; public const float BandDarkness = 0.05f; public const float ShakeAmplitude = 0.006f; public const float ShakeFrequency = 55f; public const float OffClickVolume = 0.8f; public const float OffClickStart = 0.15f; public static readonly bool UseFeedVolume = true; public const float VolumePriority = 10000f; public const float LayerRetryInterval = 2f; public const float FixedExposure = 1f; public const float SelfieGainMultiplier = 0.85f; public static readonly float[] SlabYaws = new float[3] { 0f, 72f, -72f }; public const float SlabIntensity = 0.68f; public const float SlabFaceOnScale = 1.468f; public const float SlabRange = 52f; public const float SlabBackset = 22f; public const float SlabCrossSection = 160f; public const float SlabBaseDownY = 0.42f; public const float SlabPitchFollow = 0.55f; public const float SlabMinDownY = -0.3f; public const float SlabMaxDownY = 0.78f; public const float NearLift = 1.6f; public const float NearLiftDistance = 0.5f; public const float NearShapeRadius = 0.15f; public const float NearRange = 6f; public static readonly Vector3 NearOffset = new Vector3(0.04f, -0.03f, 0.06f); public const float BatteryDrainMultiplier = 1f; public const float LowBatteryDimStart = 0.25f; public const float LowBatteryFloor = 0.35f; public const float LowBatteryFlicker = 0.12f; public static readonly bool AutoGain = true; public const float AgcTargetLuma = 0.2f; public const float AgcMeanWeight = 0.6f; public const float AgcAttackTime = 0.1f; public const float AgcReleaseTime = 1.6f; public const float AgcSampleInterval = 0.04f; public const float GrainGainQuiet = 0.3f; public const float GrainGainStraining = 1.8f; public static readonly Color Tint = new Color(0.7f, 1f, 0.44f); public const float ChannelHeadroom = 1.6f; public const float DarkLift = 0.58f; public const float ToneKnee = 0.35f; public const float ToneScale = 1.12f; public const float GrainAmount = 0.17f; public const float NoiseFloor = 0.03f; public const float GrainFps = 12f; public const float Dsnu = 0.22f; public const float HotPixelRate = 0.0006f; public const float HaloStrength = 0.35f; public const float HaloThreshold = 0.62f; public const float HaloMip = 2f; public const float SmearThreshold = 0.97f; public const float SmearStrength = 1.2f; public const float SmearLod = 4f; public const float Persistence = 0.35f; public const float VignetteMultiplier = 1f; } internal static class Cracks { public const string BakeShaderAssetName = "CrackBake"; public const string ApplyShaderAssetName = "CrackApply"; public const int ShaderRevision = 4; public const float MinFallHeight = 5f; public const int HeavyDamage = 45; public const float HitCooldown = 0.2f; public const float DropGrace = 1.5f; public const float EffectIntensity = 1f; public const float FaceDepth = 1f; public const float BakeFlipY = 0f; public const int MaskBakeWidth = 1280; public const int MaskSupersampleMax = 4; public const float CrushRadius = 0.03f; public const float CrushStrength = 0.85f; public const float Warp = 0.4f; public const float ChromaticAberration = 0.05f; public const float Darken = 0.62f; public const float Glow = 0.9f; public const float WetGlintBoost = 0.25f; public const float SpecLo = 0.34f; public const float SpecHi = 0.9f; public const float Milk = 0.18f; public const float LampRescan = 2f; public const float LampRank = 0.2f; public const float LampFade = 4f; public const float LampNear = 0.6f; public const float LampRef = 600f; public const float LampGain = 8f; public const float LampFloor = 0.01f; public const float LampSoftCap = 1.5f; public const float LampSize = 0.15f; public const float LampMinRadius = 0.5f; public const float LampMaxRadius = 4f; public const float SunRadius = 0.27f; public const float SunRef = 2f; public const float SunGain = 1.2f; } internal static class RainFeed { public const float Amount = 0.85f; public const float Wetness = 0.6f; public const float WetRampSpeed = 0.4f; public const float DryTime = 20f; public const float LookUpBaseDensity = 0.85f; public const float DropSize = 2f; public const float SlideSpeed = 1f; public const float LookUpBaseSpeed = 0.6f; public const float Inertia = 1f; public const float WindGain = 10f; public const float WindMax = 35f; public const float WindTau = 0.1f; public const float PitchFallGain = 0.06f; public const float PitchFallClamp = 0.15f; public const int FusionIterations = 1; public const float LevelInBlack = 90f; public const float LevelInWhite = 140f; public const float LevelOutBlack = 0f; public const float LevelOutWhite = 255f; public const float Distortion = 0.5f; public const float RefractGain = 0.55f; public const float SinContactAngle = 0.94f; public const float MipMax = 5f; public const float RimDark = 0.55f; public const float Fresnel = 0.12f; public const float Specular = 0.15f; } internal static class Osd { public const float ReferenceHeight = 180f; public const float Alpha = 0.92f; public static readonly bool FlipVertical = false; public const float RecBlinkRate = 1f; public const float ZoomShowTime = 1.5f; public static readonly Color White = new Color(0.93f, 0.95f, 0.94f, 1f); public static readonly Color Grey = new Color(0.72f, 0.76f, 0.74f, 1f); public static readonly Color Red = new Color(1f, 0.23f, 0.16f, 1f); public static readonly Color Amber = new Color(1f, 0.8f, 0.25f, 1f); public static readonly Color NightshotGreen = new Color(0.35f, 1f, 0.45f, 1f); public static readonly Color FocusGreen = new Color(0.35f, 1f, 0.45f, 1f); public static readonly Color MeterFill = new Color(0.35f, 0.95f, 0.75f, 1f); public static readonly Color BatteryFill = new Color(0.55f, 1f, 0.35f, 1f); public static readonly Color TrackBack = new Color(0f, 0f, 0f, 0.45f); public const float MeterFallSpeed = 2.2f; public const float MeterFloor = 40f; public const float LowBatteryLevel = 0.1f; public const int TapeLowMinutes = 1; public const int BatteryMinutesCap = 999; public const string BatteryMinutesUnknown = "----"; public const float AfReticleThreshold = 0.04f; public const float AfReticleRelease = 0.02f; public const float AfReticleHold = 0.25f; public const float AfReticleHalf = 14f; } internal static class Sfx { public const float RecordingRunStart = 1f; public const float RecordingRunEnd = 40f; public const float ButtonPressEnd = 0.35f; public const float ButtonHoldPressEnd = 0.15f; public const float ButtonHoldReleaseEnd = 0.5f; public const float CassetteEjectEnd = 0.8f; public const float HandlingMoveSpeedThreshold = 0.6f; public const float BatteryDeathSpinTime = 0.9f; public const float BatteryDeathEndPitch = 0.25f; public const float HandlingOwnVolume = 0.35f; public const float HandlingBystanderVolume = 0.25f; public const float ZoomOwnVolume = 0.2f; public const float ZoomBystanderVolume = 0.25f; public const float RecordingRunOwnVolume = 0.3f; public const float RecordingRunBystanderVolume = 0.2f; public const float ButtonPressOwnVolume = 0.3f; public const float ButtonPressBystanderVolume = 0.15f; public const float ButtonHoldOwnVolume = 0.2f; public const float ButtonHoldBystanderVolume = 0.1f; public const float CassetteEjectOwnVolume = 0.5f; public const float CassetteEjectBystanderVolume = 0.4f; public const float LensBreakOwnVolume = 0.7f; public const float LensBreakBystanderVolume = 0.55f; } internal static class Recording { public const string UnsavedFolderName = "Unsaved"; public const float MinDuration = 0.5f; public const double MinDurationGrace = 15.0; public const long MinOutputSize = 1024L; public const float EncoderFinalizeTimeout = 120f; public const float EncoderStallTimeout = 15f; public const int StderrEchoLimit = 8; public const double MergeShortfall = 0.5; public const int RetainedFrameBuffers = 48; public const float MinPaybackSlack = 0.04f; public const float MaxPaybackSlack = 0.15f; public const float JitterLimit = 0.25f; public const float IdleWakeInterval = 0.01f; public const int PrewarmedFrameBuffers = 24; public const int MaxDupBurst = 3; public const float MaxEndFill = 5f; public const float MaxLookahead = 0.05f; public const int FallbackDeficit = 2; public const float DiagnosticsWindow = 5f; public const float DiagnosticsStallThreshold = 100f; public const long SlowSpawnThreshold = 100L; public const string FfmpegDownloadUrl = "https://github.com/GyanD/codexffmpeg/releases/download/7.0.2/ffmpeg-7.0.2-essentials_build.zip"; public const int FfmpegDownloadAttempts = 3; public const int FfmpegValidateTimeout = 10000; public const int FfmpegValidateTimeoutWine = 30000; public const int PipeConnectTimeout = 15000; public const int PipeConnectTimeoutWine = 45000; public const string InputProbeArgs = "-analyzeduration 0 -probesize 32"; public const string OutputSyncArg = "-fps_mode cfr"; public const string ShortestArg = "-shortest -shortest_buf_duration 0.5"; public const string ShortestPlainArg = "-shortest"; public const string OutputFormatArg = "-f mp4"; public const int EncoderProbeMinWidth = 256; public const int EncoderProbeMinHeight = 144; public const int EncoderProbeTimeout = 8000; public const int EncoderRetryDelay = 2000; public const int EncoderErrorLines = 20; public const double AmfBaseRate = 700000.0; public const double AmfBaseArea = 102240.0; public const double AmfAreaPower = 0.85; public const int AmfQpOffset = 5; public const int MaxQp = 51; public const int WarmupFrameCount = 3; public const int StitchProbeTimeout = 10000; public const string SeamFade = "0.025"; public const int SeamDelay = 25; } internal static class Audio { public const float BleedGain = 0.1f; public const float DuckSmoothing = 8f; public const float UnderwaterCutoff = 700f; public const float UnderwaterGlideRate = 10f; public const int ShadowMaxSources = 64; public const float ShadowRadius = 45f; public const float ShadowScanInterval = 0.25f; public const int ShadowAdmitPerScan = 4; public const float ShadowMinClipLength = 0.8f; public const float ShadowMinResumeLength = 3f; public const float ShadowOrphanTime = 12f; public const float ShadowPeakDecay = 0.5f; public const int ShadowVoiceCount = 96; public const int ShadowResyncFrames = 4800; public const float ShadowFreezeDelay = 0.075f; public const long ShadowClipCacheSize = 201326592L; public const int ShadowClipReadAttempts = 8; public const float ShadowLiveRefreshInterval = 0.4f; public const float ShadowCurveRefreshInterval = 5f; public const float ShadowRolloffScale = 1f; public const float ShadowSfxGroupGain = 1.2589f; public const float ShadowVoiceGroupGain = 1.5849f; public const float ShadowCentreGain = 0.70710677f; public const float ShadowSpreadFlatGain = 0.5f; public const float ShadowWeatherIndoorGain = 0.1f; public const float ShadowOwnCameraGain = 0.5f; public const float ShadowOccludeCheckInterval = 0.5f; public const float ShadowOccludeOpenCutoff = 10000f; public const float ShadowOccludeMinCutoff = 900f; public const float ShadowOccludeMaxCutoff = 4000f; public const float ShadowOccludeScale = 2500f; public const float ShadowOccludeGlide = 8f; public const float ShadowOccludeRangeSqr = 12100f; public const float ShadowOccludeBypassCutoff = 22000f; public const float ShadowOccludeGain = 0.5f; public const float ShadowOccludeCloseTime = 0.1f; public const float ShadowOccludeClearTime = 1f; public const float ShadowOccludeSelfRadius = 0.1f; public const float ShadowVoiceScanInterval = 1f; public const float ShadowVoiceLevel = 1f; public const float HeldRoomDistance = 1.2f; public const float NearReference = 0.6f; public const float NearExponent = 0.4f; public const float NearFloor = 0.5f; public const float VoiceRange = 50f; public const float VoiceSpread = 30f; public const int MicQueueLimit = 12000; public const float MicPreRollTime = 0.04f; public const float MicFadeTime = 0.01f; public const float VoiceGateTime = 0.1f; public const float ShadowVoiceFleaCutoff = 500f; public const float ShadowVoiceMaskCutoff = 300f; public const float ShadowVoiceUnderwaterCutoff = 600f; public const float ShadowVoiceDirectivityLow = -4f; public const float ShadowVoiceDirectivityHigh = -20f; public const float ShadowVoiceDirectivityCorner = 2500f; public const float ShadowVoiceEchoDistance = 60f; public const float ShadowVoiceEchoDelay = 0.5f; public const float ShadowVoiceEchoDry = 0.5f; public const float ShadowVoiceEchoWet = 0.35f; public const float ShadowVoiceEchoFeedback = 0.3f; public const float ShadowVoiceEchoRise = 0.2f; public const float ShadowVoiceEchoFall = 1f; public const float EchoIndoorDistance = 6f; public const float EchoOutdoorDistance = 40f; public const float EchoIndoorDecay = 1.8f; public const float EchoOutdoorDecay = 0.6f; public const float ShadowReverbDecayInside = 1.8f; public const float ShadowReverbDamping = 0.35f; public const float ShadowReverbPreDelay = 0.02f; public const float ShadowReverbOutputGain = 0.048f; public const float ShadowReportInterval = 5f; public const float ShadowCensusInterval = 5f; public const float MicHighPass = 120f; public const float MicLowPass = 15000f; public const float MicPresence = 3200f; public const float MicPresenceGain = 4f; public const float MicSideHighPass = 5716f; public const float MicStereoWidth = 1f; public const float MicNominalLevel = 0.12589f; public const float MicAttackTime = 0.0011f; public const float MicHoldTime = 0.25f; public const float MicNoiseFloorLevel = 0.000251f; public const float MicLimitThreshold = 0.1841f; public const float MicLimitAttackTime = 0.001f; public const float MicLimitHoldTime = 0.03f; public const float MicLimitReleaseTime = 0.15f; public const float MicNoiseAmplitude = 0.0006f; public const float MicClipDrive = 1.05f; public const float MicEchoHeadroom = 8f; } internal static class Cassette { public const string ItemAssetName = "CassetteItem"; public const string PrefabAssetName = "Cassette"; public const string ItemKey = "video_cassette"; public const int HudUtilitySlotIndex = 50; public const float ReconcileDelay = 3f; public const float EncodeTimeout = 150f; public const int MaxSaveNameLength = 64; public const int MaxScanRange = 13; public const int MinScanRange = 1; public const float MinSoundDistance = 1f; public const float MaxSoundDistance = 25f; public const int FloorRaycastMask = 268437760; public const float EjectRestHeightOffset = 0.1f; public const float RestHeight = 0.016f; public const string ColorObjectName = "cassettecolor"; public const int ColorHueBuckets = 12; public const string IconAssetPrefix = "CassetteIcon_"; public const string IconLegendaryKey = "l00"; public const string IconGoldKey = "g00"; public const string IconHoloKey = "h00"; public const string IconMisprintKey = "x00"; public const int ColorUncommonValue = 30; public const int ColorRareValue = 80; public const int ColorLegendaryValue = 150; public const int ColorGoldValue = 250; public const int ColorHoloValue = 400; public const int StripeRows = 8; public const float StripeRowInset = 0.04f; public const float StripeSmoothness = 0.4f; public const float GoldMetallic = 0.45f; public const float GoldSmoothness = 0.65f; public const float HoloMetallic = 0.35f; public const float HoloSmoothness = 0.8f; public const float HoloShimmerSpeed = 0.08f; public const float HoloShimmerSaturation = 0.25f; public const int MisprintChance = 128; public const float MisprintRowShift = 0.3f; } internal static class Bounty { public const string ConfigSection = "9. Bounties"; public const int MinBounty = 0; public const int MaxBounty = 500; public const float RateToCredits = 30f; public const float DefaultRate = 1f; public const float PowerLevelScale = 0.5f; public const float SampleRate = 4f; public const float MaxDistance = 45f; public const float FramingBonus = 0.25f; public const float SharedShotBonus = 0.15f; public const float KillBonus = 1f; public const float KillWindow = 2.5f; public const float FirstFootageBonus = 1f; public static readonly Vector2[] FramingKeys = (Vector2[])(object)new Vector2[6] { new Vector2(0f, 0f), new Vector2(0.05f, 0.3f), new Vector2(0.15f, 0.7f), new Vector2(0.4f, 1f), new Vector2(0.7f, 0.7f), new Vector2(1f, 0.35f) }; public const int LowPowerCredits = 15; public const float OpenTakeGrace = 120f; public const float DangerReference = 575f; public const float MinDanger = 0.75f; public const float MaxDanger = 2f; public const int MaxRows = 256; public const float MaxRowTime = 3600f; public const int MaxValue = 250000; public const float ValueCeilingHeadroom = 2f; } internal static class Terminal { public const string KeywordPlay = "play"; public const string KeywordStop = "stop"; public const string KeywordSave = "save"; public const string KeywordDelete = "delete"; public const string KeywordList = "cassettes"; public const string KeywordSlow = "slow"; public const string KeywordNormal = "normal"; public const string KeywordFast = "fast"; public const string KeywordTurbo = "turbo"; public const string KeywordPause = "pause"; public const string KeywordResume = "resume"; public const string KeywordVolume = "volume"; public const string KeywordTransfer = "transfer"; public const string EventPlay = "vc_cassette_play"; public const string EventStop = "vc_cassette_stop"; public const string EventSave = "vc_cassette_save"; public const string EventDelete = "vc_cassette_delete"; public const string EventList = "vc_cassette_list"; public const string EventHelp = "vc_cassette_help"; public const string EventSlow = "vc_cassette_speed_slow"; public const string EventNormal = "vc_cassette_speed_normal"; public const string EventFast = "vc_cassette_speed_fast"; public const string EventTurbo = "vc_cassette_speed_turbo"; public const string EventPause = "vc_cassette_pause"; public const string EventResume = "vc_cassette_resume"; public const string EventVolume = "vc_cassette_volume"; public const string EventTransfer = "vc_cassette_transfer"; public const float StatusFontScale = 1.6f; public const float StatusFallbackFontSize = 28f; public const int PlaybackAnswerOffset = 17; public const float PlaybackAudioMaxDistance = 18f; public const double SiblingCheckInterval = 0.25; public const double PlaybackHitchThreshold = 100.0; public const double PlaybackHitchLogCooldown = 1.0; public const float TransferSilenceTimeout = 120f; public const float MissingFileGrace = 10f; public const double FileCheckInterval = 0.25; } internal static class Monitor { public const int TransferIndex = 0; public const int ScanLimit = 64; public const double PrepareTimeout = 8.0; public const double ReapplyInterval = 0.25; public const double ReapplyLogCooldown = 5.0; public const double StateReportDelay = 2.0; public const string ScreenLightPrefabName = "OperatorScreenLight"; public const string ScreenLightAnchorName = "MonitorWall"; public static readonly Vector3 ScreenLightLocalPosition = new Vector3(-0.17513478f, -1.8971599f, -2.1490002f); public static readonly Quaternion ScreenLightLocalRotation = new Quaternion(0f, -0.59619886f, 0f, 0.8028368f); public const float ScreenLightMaxOffset = 0.5f; public static readonly Vector3 VanillaScreenLocalCenter = new Vector3(-0.1885279f, 0.9308863f, -0.0623014f); public static readonly Vector3 VanillaScreenLocalExtents = new Vector3(0.2259891f, 0.7443714f, 0.5985336f); public const float LightMidLuma = 0.22f; public const float LightContrast = 0.75f; public const float LightMin = 0.25f; public const float LightMax = 3f; public const float LightResponseSpeed = 12f; public const float LightMaxSaturation = 0.3f; public const float LightDarkLumaThreshold = 0.05f; public const float LightFlickerAmount = 0.04f; public const float LightFlickerSpeed = 10f; public const int LightProbeSize = 64; public const float LightSampleInterval = 0.08f; } internal static class Television { public const string DeckPrefabAssetName = "CassetteDeck"; public const float AttachPollInterval = 1f; public static readonly Vector3 DeckLocalPosition = new Vector3(0.49f, 0.95f, -0.27f); public static readonly Vector3 DeckLocalEuler = new Vector3(0f, 0f, 0f); public static readonly Vector3 DeckLocalScale = new Vector3(1f, 1f, 1f); public const int ScreenMaterialIndex = 1; public const string ScreenBaseColor = "_BaseColor"; public const string ScreenEmissiveColor = "_EmissiveColor"; public const float ScreenGlow = 4f; public const float OutlineScale = 1.04f; public const float PlaybackAudioMaxDistance = 22f; public const string TriggerInsert = "insert"; public const string TriggerStartStop = "startstop"; public const string TriggerPauseResume = "pasres"; public const string TriggerSpeedUp = "speedu"; public const string TriggerSpeedDown = "speedd"; public const string TriggerVolume = "volume"; public const string StateStop = "stopb"; public const string StateStopUp = "stopbUp"; public const string StateResume = "resumeb"; public const string StateResumeUp = "resumebUp"; public const string StateSpeedDown = "speeddown"; public const string StateSpeedUp = "speedup"; public const string StateEject = "ejectb"; public const string StateLoadIn = "LoadIn"; public const string StateLoadOut = "LoadOut"; public const string StateReelSpin = "ReelSpin"; public const string ReelSpeedParameter = "ReelSpeed"; public const float LocalPressHold = 0.75f; public const float EndGrace = 0.75f; public const string Frame1ObjectName = "frame1"; public const string Frame2ObjectName = "frame2"; public const string VolumeKnobObjectName = "volumescroll"; public const string VolumeArrowObjectName = "arrow"; public const string DisplayObjectName = "display"; public const string DisplayEmissiveMap = "_EmissiveColorMap"; public const int DisplayWidth = 840; public const int DisplayHeight = 160; public const float DisplayRedrawInterval = 0.25f; public const string LampObjectName = "lampLens"; public const string LampEmissiveColor = "_EmissiveColor"; public const string IdleClock = "12:00"; public const float ClockBlinkInterval = 0.5f; public const string KeySoundObjectName = "DeckKeys"; public const string MechSoundObjectName = "DeckMech"; public const string MotorSoundObjectName = "DeckMotor"; public static readonly Vector3 SoundLocalPosition = new Vector3(0f, 0.25f, 0.25f); public const float SoundMinDistance = 1f; public const float SoundMaxDistance = 14f; public const float KeyVolume = 0.7f; public const float LoadVolume = 0.9f; public const float EjectVolume = 0.9f; public const float MotorVolume = 0.24f; public const float PlaybackGain = 2.5f; public const float LimiterCeiling = 0.89f; public const float LimiterRelease = 0.15f; public const string MicrowaveUnlockable = "Microwave"; public const string BoomboxItem = "Boombox"; public static readonly string[] KeyClips = new string[2] { "ButtonPress1_0", "ButtonPress2" }; public const string LoadClip = "MicrowaveClose"; public const string EjectClip = "BoomboxStop"; public const string MotorClip = "MicrowaveWhir"; public const string GhostObjectName = "ghost"; public const string GhostRendererName = "DeckGhost"; public const string OutlineRendererName = "DeckOutline"; public const float VolumeMin = 0.1f; public const float VolumeStep = 0.1f; public const float VolumeMinAngle = 144f; public const float VolumeStepAngle = 32f; public const float LightMidLuma = 0.22f; public const float LightContrast = 0.75f; public const float LightMin = 0.25f; public const float LightMax = 3f; public const float LightResponseSpeed = 12f; public const float LightMaxSaturation = 0.3f; public const float LightDarkLumaThreshold = 0.05f; public const float LightFlickerAmount = 0.04f; public const float LightFlickerSpeed = 10f; public const int LightProbeSize = 16; public const float LightSampleInterval = 0.08f; public static readonly Color BacklightColor = new Color(0.82f, 0.88f, 1f); public const float InsertSlideTime = 1.3f; public const float SlotOutsideOffset = 0.22f; public const float SlotInsideDepth = 0.119f; public const float BasketDrop = 0.028f; public const float InsertDrawStart = 0.08f; public const float InsertDrawEnd = 0.57f; public const float InsertDropStart = 0.45f; public const float InsertDropEnd = 0.77f; public const float InsertBuzzAmplitude = 0.0004f; public const float InsertBuzzRate = 56f; public static readonly Vector3 VisualLocalScale = Vector3.one; public const float FlapMass = 0.06f; public const float FlapAngularDrag = 2.5f; public const float FlapHingeSpring = 22f; public const float FlapHingeDamper = 2.5f; public const float FlapHingeMinAngle = -60f; public const float FlapHingeMaxAngle = 60f; public static readonly Vector3 FlapHingeAxis = Vector3.right; public const float FlapInsertOpenSpeed = 3.5f; public const float FlapEjectOpenSpeed = 8f; public const float DeckEjectOutForce = 2f; public const float DeckEjectUpForce = 1.5f; public const float DeckEjectSettleVelocity = 0.18f; public const float DeckEjectSettleTimeout = 6f; public const float DeckEjectCrazyChance = 0.08f; public const float DeckEjectCrazyMultiplier = 2.5f; } } internal static class ModGUIDs { public const string InputUtils = "com.rune580.LethalCompanyInputUtils"; public const string CullFactory = "com.fumiko.CullFactory"; public const string GeneralImprovements = "ShaosilGaming.GeneralImprovements"; public const string LethalConfig = "ainavt.lc.lethalconfig"; public const string MoreShipUpgrades = "com.malco.lethalcompany.moreshipupgrades"; public const string OpenBodyCams = "Zaggy1024.OpenBodyCams"; public const string Jll = "JacobG5.JLL"; public const string BetterScanVision = "DBJ.BetterScanVision"; public const string LethalSponge = "LethalSponge"; public const string Lcvr = "io.daxcess.lcvr"; } [BepInPlugin("com.seeya.operator", "Operator", "1.0.0")] [BepInDependency("com.github.teamxiaolan.dawnlib", "0.9.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private readonly Harmony _harmony = new Harmony("com.seeya.operator"); public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } internal static OperatorInputs Inputs { get; private set; } private static void RegisterNetworkVariableTypes() { try { NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<bool>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<bool>(); NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<int>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<int>(); NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<float>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<float>(); NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<double>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<double>(); } catch (Exception ex) { Log.LogWarning((object)("Could not register network variable types, " + ex.Message)); } } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; RegisterNetworkVariableTypes(); VideoCameraConfig.Initialize(((BaseUnityPlugin)this).Config); Inputs = new OperatorInputs(); VideoCameraRegistrar.Register(); CassetteRegistrar.Register(); CassetteLibrary.Load(); EnemyBountyLoader.Hook(); AssetsLoader.WarmAudioClips(); _harmony.PatchAll(); LethalSpongeCompat.Init(); if (VideoCameraConfig.RecordingEnabled.Value) { PrewarmRecording(); } Application.quitting += OnApplicationQuitting; Log.LogInfo((object)"Operator is loaded!"); } private static void PrewarmRecording() { FfmpegLocator.InitAsync().ContinueWith((Task<bool> _) => VideoEncoder.PrewarmAsync(), TaskScheduler.Default); try { Directory.CreateDirectory(Recorder.GetOutputDirectory()); Directory.CreateDirectory(Recorder.GetActiveRecordingDirectory()); } catch (Exception ex) { Log.LogDebug((object)("Could not create recording directories yet: " + ex.Message)); } int width = 32; int height = 32; try { var (captureWidth, captureHeight) = VideoCameraConfig.G