using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("3RdPersonCoeeEX")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Third-person camera switching for Lethal Company.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("3RdPersonCoeeEX")] [assembly: AssemblyTitle("3RdPersonCoeeEX")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 ProjectFolderName { public enum CameraSwitchingMethod { Toggle, Wheel, Off } internal sealed class InGameCameraSettingsMenu : MonoBehaviour { private const float ScanInterval = 0.35f; private float nextScanTime; private bool settingsScreenVisible; private GUIStyle? titleStyle; private GUIStyle? labelStyle; private GUIStyle? buttonStyle; private GUIStyle? boxStyle; private Texture2D? whiteTexture; private void Update() { if (!(Time.unscaledTime < nextScanTime)) { nextScanTime = Time.unscaledTime + 0.35f; settingsScreenVisible = Plugin.ShowInGameSettings.Value && IsVanillaSettingsScreenVisible(); } } private void OnGUI() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) if (settingsScreenVisible) { EnsureStyles(); float num = (float)Screen.width / 1920f; float num2 = (float)Screen.height / 1080f; float num3 = 412f * num; float num4 = 382f * num2; Rect val = default(Rect); ((Rect)(ref val))..ctor(520f * num, 482f * num2, num3, num4); GUI.Box(val, GUIContent.none, boxStyle); DrawBorder(val, 2f * Mathf.Min(num, num2)); GUI.Label(new Rect(((Rect)(ref val)).x + 20f * num, ((Rect)(ref val)).y + 18f * num2, ((Rect)(ref val)).width - 40f * num, 42f * num2), "SWITCH CAMERA", titleStyle); GUI.Label(new Rect(((Rect)(ref val)).x + 20f * num, ((Rect)(ref val)).y + 88f * num2, ((Rect)(ref val)).width - 40f * num, 28f * num2), "Camera switching method", labelStyle); if (GUI.Button(new Rect(((Rect)(ref val)).x + 20f * num, ((Rect)(ref val)).y + 124f * num2, ((Rect)(ref val)).width - 40f * num, 54f * num2), $"> {Plugin.SwitchingMethod.Value}", buttonStyle)) { VanillaButtonSound.Play(); CycleMethod(); } GUI.Label(new Rect(((Rect)(ref val)).x + 20f * num, ((Rect)(ref val)).y + 216f * num2, ((Rect)(ref val)).width - 40f * num, 28f * num2), "Preserve height / distance", labelStyle); if (GUI.Button(new Rect(((Rect)(ref val)).x + 20f * num, ((Rect)(ref val)).y + 252f * num2, ((Rect)(ref val)).width - 40f * num, 54f * num2), "> " + (Plugin.PreserveCameraAdjustments.Value ? "On" : "Off"), buttonStyle)) { VanillaButtonSound.Play(); TogglePreserveAdjustments(); } } } private static void CycleMethod() { ConfigEntry switchingMethod = Plugin.SwitchingMethod; switchingMethod.Value = Plugin.SwitchingMethod.Value switch { CameraSwitchingMethod.Toggle => CameraSwitchingMethod.Wheel, CameraSwitchingMethod.Wheel => CameraSwitchingMethod.Off, _ => CameraSwitchingMethod.Toggle, }; ((ConfigEntryBase)Plugin.SwitchingMethod).ConfigFile.Save(); Plugin.Log.LogInfo((object)$"Camera switching method set to {Plugin.SwitchingMethod.Value} from in-game settings."); } private static void TogglePreserveAdjustments() { Plugin.PreserveCameraAdjustments.Value = !Plugin.PreserveCameraAdjustments.Value; ((ConfigEntryBase)Plugin.PreserveCameraAdjustments).ConfigFile.Save(); Plugin.Log.LogInfo((object)$"Preserve camera height and distance set to {Plugin.PreserveCameraAdjustments.Value} from in-game settings."); } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Expected O, but got Unknown //IL_01d6: Expected O, but got Unknown if (titleStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.box) { border = new RectOffset(2, 2, 2, 2), margin = new RectOffset(0, 0, 0, 0), padding = new RectOffset(0, 0, 0, 0) }; val.normal.background = Texture2D.blackTexture; val.normal.textColor = Color.white; boxStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = Mathf.RoundToInt(32f * Mathf.Min((float)Screen.width / 1920f, (float)Screen.height / 1080f)) }; val2.normal.textColor = new Color(1f, 0.18f, 0.25f); val2.alignment = (TextAnchor)3; titleStyle = val2; GUIStyle val3 = new GUIStyle(GUI.skin.label) { fontSize = Mathf.RoundToInt(22f * Mathf.Min((float)Screen.width / 1920f, (float)Screen.height / 1080f)) }; val3.normal.textColor = Color.white; val3.alignment = (TextAnchor)3; labelStyle = val3; GUIStyle val4 = new GUIStyle(GUI.skin.button) { fontSize = Mathf.RoundToInt(22f * Mathf.Min((float)Screen.width / 1920f, (float)Screen.height / 1080f)) }; val4.normal.textColor = Color.white; val4.hover.textColor = new Color(1f, 0.45f, 0.05f); val4.active.textColor = new Color(1f, 0.45f, 0.05f); val4.alignment = (TextAnchor)3; val4.padding = new RectOffset(16, 8, 4, 4); buttonStyle = val4; } } private void DrawBorder(Rect rect, float thickness) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if (whiteTexture == null) { whiteTexture = Texture2D.whiteTexture; } Color color = GUI.color; GUI.color = Color.white; GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), (Texture)(object)whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), (Texture)(object)whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), (Texture)(object)whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), (Texture)(object)whiteTexture); GUI.color = color; } private static bool IsVanillaSettingsScreenVisible() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) bool flag = false; bool flag2 = false; Component[] array = Resources.FindObjectsOfTypeAll(); foreach (Component val in array) { if ((Object)(object)val == (Object)null) { continue; } Scene scene = val.gameObject.scene; if (!((Scene)(ref scene)).IsValid() || !val.gameObject.activeInHierarchy) { continue; } string text = GetText(val); if (!string.IsNullOrWhiteSpace(text)) { if (text.Equals("ACCESSIBILITY", StringComparison.OrdinalIgnoreCase)) { flag = true; } if (text.Equals("GRAPHICS", StringComparison.OrdinalIgnoreCase) || text.Equals("DISPLAY", StringComparison.OrdinalIgnoreCase)) { flag2 = true; } if (flag && flag2) { return true; } } } return false; } private static string? GetText(Component component) { PropertyInfo property = ((object)component).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public); if (!(property?.PropertyType == typeof(string))) { return null; } return property.GetValue(component) as string; } } internal static class InputSystemReader { private static bool initialized; private static bool loggedMissingInputSystem; private static Type? keyboardType; private static Type? mouseType; private static PropertyInfo? keyboardCurrentProperty; private static PropertyInfo? mouseCurrentProperty; private static PropertyInfo? f5KeyProperty; private static PropertyInfo? leftAltKeyProperty; private static PropertyInfo? rightAltKeyProperty; private static PropertyInfo? upArrowKeyProperty; private static PropertyInfo? downArrowKeyProperty; private static PropertyInfo? leftArrowKeyProperty; private static PropertyInfo? rightArrowKeyProperty; private static PropertyInfo? wKeyProperty; private static PropertyInfo? sKeyProperty; private static PropertyInfo? scrollProperty; private static PropertyInfo? wasPressedThisFrameProperty; private static PropertyInfo? isPressedProperty; private static MethodInfo? readScrollValueMethod; public static bool WasF5PressedThisFrame() { EnsureInitialized(); if (keyboardCurrentProperty == null || f5KeyProperty == null || wasPressedThisFrameProperty == null) { return false; } object value = keyboardCurrentProperty.GetValue(null); object obj = ((value == null) ? null : f5KeyProperty.GetValue(value)); if (obj != null) { object value2 = wasPressedThisFrameProperty.GetValue(obj); if (value2 is bool) { return (bool)value2; } return false; } return false; } public static float ReadMouseScrollY() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) EnsureInitialized(); if (mouseCurrentProperty == null || scrollProperty == null || readScrollValueMethod == null) { return 0f; } object value = mouseCurrentProperty.GetValue(null); object obj = ((value == null) ? null : scrollProperty.GetValue(value)); object obj2 = ((obj == null) ? null : readScrollValueMethod.Invoke(obj, Array.Empty())); if (obj2 is Vector2) { return ((Vector2)obj2).y; } return ReadYByReflection(obj2); } public static bool IsAltPressed() { EnsureInitialized(); if (!IsKeyPressed(leftAltKeyProperty)) { return IsKeyPressed(rightAltKeyProperty); } return true; } public static bool IsUpPressed() { EnsureInitialized(); if (!IsKeyPressed(upArrowKeyProperty)) { return IsKeyPressed(wKeyProperty); } return true; } public static bool IsDownPressed() { EnsureInitialized(); if (!IsKeyPressed(downArrowKeyProperty)) { return IsKeyPressed(sKeyProperty); } return true; } public static bool IsLeftPressed() { EnsureInitialized(); return IsKeyPressed(leftArrowKeyProperty); } public static bool IsRightPressed() { EnsureInitialized(); return IsKeyPressed(rightArrowKeyProperty); } public static bool IsWPressed() { EnsureInitialized(); return IsKeyPressed(wKeyProperty); } public static bool IsSPressed() { EnsureInitialized(); return IsKeyPressed(sKeyProperty); } private static void EnsureInitialized() { if (!initialized) { initialized = true; keyboardType = FindType("UnityEngine.InputSystem.Keyboard"); mouseType = FindType("UnityEngine.InputSystem.Mouse"); keyboardCurrentProperty = keyboardType?.GetProperty("current", BindingFlags.Static | BindingFlags.Public); mouseCurrentProperty = mouseType?.GetProperty("current", BindingFlags.Static | BindingFlags.Public); f5KeyProperty = keyboardType?.GetProperty("f5Key", BindingFlags.Instance | BindingFlags.Public); leftAltKeyProperty = keyboardType?.GetProperty("leftAltKey", BindingFlags.Instance | BindingFlags.Public); rightAltKeyProperty = keyboardType?.GetProperty("rightAltKey", BindingFlags.Instance | BindingFlags.Public); upArrowKeyProperty = keyboardType?.GetProperty("upArrowKey", BindingFlags.Instance | BindingFlags.Public); downArrowKeyProperty = keyboardType?.GetProperty("downArrowKey", BindingFlags.Instance | BindingFlags.Public); leftArrowKeyProperty = keyboardType?.GetProperty("leftArrowKey", BindingFlags.Instance | BindingFlags.Public); rightArrowKeyProperty = keyboardType?.GetProperty("rightArrowKey", BindingFlags.Instance | BindingFlags.Public); wKeyProperty = keyboardType?.GetProperty("wKey", BindingFlags.Instance | BindingFlags.Public); sKeyProperty = keyboardType?.GetProperty("sKey", BindingFlags.Instance | BindingFlags.Public); scrollProperty = mouseType?.GetProperty("scroll", BindingFlags.Instance | BindingFlags.Public); Type obj = f5KeyProperty?.PropertyType; wasPressedThisFrameProperty = obj?.GetProperty("wasPressedThisFrame", BindingFlags.Instance | BindingFlags.Public); isPressedProperty = obj?.GetProperty("isPressed", BindingFlags.Instance | BindingFlags.Public); readScrollValueMethod = (scrollProperty?.PropertyType)?.GetMethod("ReadValue", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); if (!loggedMissingInputSystem && (keyboardCurrentProperty == null || mouseCurrentProperty == null)) { loggedMissingInputSystem = true; Plugin.Log.LogWarning((object)"Unity Input System was not found; keyboard and wheel camera controls are unavailable."); } } } private static bool IsKeyPressed(PropertyInfo? keyProperty) { if (keyboardCurrentProperty == null || keyProperty == null || isPressedProperty == null) { return false; } object value = keyboardCurrentProperty.GetValue(null); object obj = ((value == null) ? null : keyProperty.GetValue(value)); if (obj != null) { object value2 = isPressedProperty.GetValue(obj); if (value2 is bool) { return (bool)value2; } return false; } return false; } private static float ReadYByReflection(object? value) { if (value == null) { return 0f; } Type type = value.GetType(); object obj = type.GetProperty("y", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value); if (obj is float) { return (float)obj; } obj = type.GetField("y", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value); if (obj is float) { return (float)obj; } return 0f; } private static Type? FindType(string typeName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(typeName, throwOnError: false); if (type != null) { return type; } } return null; } } [BepInPlugin("projectfoldername.3rdpersoncoeeex", "3RdPersonCoeeEX", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry SwitchingMethod; internal static ConfigEntry ShowInGameSettings; internal static ConfigEntry PreserveCameraAdjustments; private void Awake() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; SwitchingMethod = ((BaseUnityPlugin)this).Config.Bind("switch camera", "Camera switching method", CameraSwitchingMethod.Toggle, "Toggle: F5 cycles first/back/front like Minecraft. Wheel: mouse wheel freely adjusts first-to-third person like Roblox. Off: disables 3RdPersonCoeeEX."); ShowInGameSettings = ((BaseUnityPlugin)this).Config.Bind("switch camera", "Show in-game settings", true, "Shows the 3RdPersonCoeeEX camera setting directly on Lethal Company's in-game settings screen."); PreserveCameraAdjustments = ((BaseUnityPlugin)this).Config.Bind("switch camera", "Preserve camera height and distance", false, "Keeps Alt camera height/distance adjustments after returning to first person."); GameObject val = new GameObject("3RdPersonCoeeEX.CameraController"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; val.AddComponent(); val.AddComponent(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"3RdPersonCoeeEX 1.0.0 loaded."); } } internal static class PluginInfo { public const string Guid = "projectfoldername.3rdpersoncoeeex"; public const string Name = "3RdPersonCoeeEX"; public const string Version = "1.0.0"; } internal sealed class ThirdPersonCameraController : MonoBehaviour { private enum ToggleView { FirstPerson, Back, Front } private const float MinWheelDistance = 0f; private const float MaxWheelDistance = 6f; private const float WheelStep = 1.1f; private const float AltWheelStep = 0.65f; private const float HeightAdjustSpeed = 1.8f; private const float DistanceAdjustSpeed = 2.6f; private const float MinHeightOffset = -1.1f; private const float MaxHeightOffset = 2.2f; private const float MinDistanceOffset = -2.4f; private const float MaxDistanceOffset = 4.5f; private const float MinThirdPersonDistance = 0.35f; private const float MaxThirdPersonDistance = 10f; private const float ShoulderOffset = 0.35f; private const float PivotHeight = 1.55f; private const float CollisionPadding = 0.18f; private object? player; private Camera? camera; private Camera? thirdPersonCamera; private Transform? playerTransform; private float wheelDistance; private float heightOffset; private float distanceOffset; private float lastToggleTime = -1f; private ToggleView toggleView; private bool cameraCaptured; private bool localBodyWasShadowOnly; private bool thirdPersonActive; private Type? startOfRoundType; private void Update() { if (ShouldSuppressForwardBackMovement()) { SuppressForwardBackMovement(); } } private void LateUpdate() { CameraSwitchingMethod value = Plugin.SwitchingMethod.Value; CaptureLocalPlayer(); if (player == null || (Object)(object)camera == (Object)null || value == CameraSwitchingMethod.Off || IsPlayerDead(player)) { RestoreFirstPerson(); } else if (value == CameraSwitchingMethod.Toggle) { HandleToggleInput(); if (toggleView == ToggleView.FirstPerson) { RestoreFirstPersonIfNeeded(); return; } float signedDistance = ((toggleView == ToggleView.Back) ? 3.5f : (-3.5f)); ApplyThirdPerson(signedDistance); } else { HandleWheelInput(); if (wheelDistance <= 0.05f) { RestoreFirstPersonIfNeeded(); } else { ApplyThirdPerson(wheelDistance); } } } private void CaptureLocalPlayer() { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Invalid comparison between Unknown and I4 object localPlayer = GetLocalPlayer(); if (localPlayer == null || (localPlayer == player && cameraCaptured)) { return; } RestoreFirstPerson(); player = localPlayer; object obj = ((localPlayer is Component) ? localPlayer : null); playerTransform = ((obj != null) ? ((Component)obj).transform : null); camera = GetFieldOrProperty(localPlayer, "gameplayCamera"); if (!((Object)(object)camera == (Object)null)) { cameraCaptured = true; thirdPersonActive = false; wheelDistance = 0f; toggleView = ToggleView.FirstPerson; SkinnedMeshRenderer fieldOrProperty = GetFieldOrProperty(localPlayer, "thisPlayerModel"); if ((Object)(object)fieldOrProperty != (Object)null) { localBodyWasShadowOnly = (int)((Renderer)fieldOrProperty).shadowCastingMode == 3; } } } private void HandleToggleInput() { if (InputSystemReader.WasF5PressedThisFrame() && !(Time.unscaledTime - lastToggleTime < 0.25f)) { lastToggleTime = Time.unscaledTime; toggleView = toggleView switch { ToggleView.FirstPerson => ToggleView.Back, ToggleView.Back => ToggleView.Front, _ => ToggleView.FirstPerson, }; } } private void HandleWheelInput() { float num = InputSystemReader.ReadMouseScrollY(); if (!(Math.Abs(num) < 0.01f)) { float num2 = ((InputSystemReader.IsAltPressed() && thirdPersonActive) ? 0.65f : 1.1f); wheelDistance = Mathf.Clamp(wheelDistance - num * num2, 0f, 6f); } } private void ApplyThirdPerson(float signedDistance) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) if (player == null || (Object)(object)playerTransform == (Object)null || (Object)(object)camera == (Object)null) { return; } EnsureThirdPersonCamera(); ShowLocalBody(visible: true); HandleAltCameraAdjustments(); if (ShouldSuppressForwardBackMovement()) { SuppressForwardBackMovement(); } Camera val = thirdPersonCamera; if (!((Object)(object)val == (Object)null)) { Vector3 val2 = playerTransform.position + Vector3.up * (1.55f + heightOffset); Vector3 forward = playerTransform.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.001f) { forward = Vector3.forward; } ((Vector3)(ref forward)).Normalize(); Vector3 val3 = Vector3.Cross(Vector3.up, forward); Vector3 normalized = ((Vector3)(ref val3)).normalized; bool flag = signedDistance >= 0f; float num = Mathf.Clamp(Mathf.Abs(signedDistance) + distanceOffset, 0.35f, 10f); Vector3 val4 = (flag ? (-forward) : forward); Vector3 val5 = normalized * 0.35f; Vector3 desired = val2 + val5 + val4 * num; Vector3 position = ResolveCameraCollision(val2 + val5, desired); Vector3 val6 = ((Component)camera).transform.forward; if (((Vector3)(ref val6)).sqrMagnitude < 0.001f) { val6 = forward; } ((Component)val).transform.position = position; ((Component)val).transform.rotation = Quaternion.LookRotation(flag ? val6 : (-val6), Vector3.up); thirdPersonActive = true; } } private Vector3 ResolveCameraCollision(Vector3 pivot, Vector3 desired) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Vector3 val = desired - pivot; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.01f) { return desired; } RaycastHit val2 = default(RaycastHit); if (Physics.SphereCast(pivot, 0.18f, ((Vector3)(ref val)).normalized, ref val2, magnitude, -1, (QueryTriggerInteraction)1)) { return pivot + ((Vector3)(ref val)).normalized * Mathf.Max(0.1f, ((RaycastHit)(ref val2)).distance - 0.18f); } return desired; } private void RestoreFirstPerson() { if (thirdPersonActive) { RestoreFirstPersonIfNeeded(); } } private void RestoreFirstPersonIfNeeded() { if (cameraCaptured && !((Object)(object)camera == (Object)null)) { ShowLocalBody(visible: false); if ((Object)(object)camera != (Object)null) { ((Behaviour)camera).enabled = true; } if ((Object)(object)thirdPersonCamera != (Object)null) { Object.Destroy((Object)(object)((Component)thirdPersonCamera).gameObject); thirdPersonCamera = null; } thirdPersonActive = false; ResetAdjustmentsIfNeeded(); } } private void HandleAltCameraAdjustments() { if (InputSystemReader.IsAltPressed()) { float unscaledDeltaTime = Time.unscaledDeltaTime; float num = 0f; float num2 = 0f; if (InputSystemReader.IsUpPressed()) { num += 1f; } if (InputSystemReader.IsDownPressed()) { num -= 1f; } if (InputSystemReader.IsRightPressed()) { num2 += 1f; } if (InputSystemReader.IsLeftPressed()) { num2 -= 1f; } if (Math.Abs(num) > 0.01f) { heightOffset = Mathf.Clamp(heightOffset + num * 1.8f * unscaledDeltaTime, -1.1f, 2.2f); } if (Math.Abs(num2) > 0.01f) { distanceOffset = Mathf.Clamp(distanceOffset + num2 * 2.6f * unscaledDeltaTime, -2.4f, 4.5f); } } } private bool ShouldSuppressForwardBackMovement() { if (thirdPersonActive && InputSystemReader.IsAltPressed()) { if (!InputSystemReader.IsWPressed()) { return InputSystemReader.IsSPressed(); } return true; } return false; } private void SuppressForwardBackMovement() { if (player != null && !TryZeroMovementY(player, "moveInputVector") && !TryZeroMovementY(player, "movementInput")) { TryZeroMovementY(player, "moveInput"); } } private static bool TryZeroMovementY(object instance, string memberName) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) Type type = instance.GetType(); FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(Vector2) && field.GetValue(instance) is Vector2 val) { val.y = 0f; field.SetValue(instance, val); return true; } PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(Vector2) && property.CanRead && property.CanWrite && property.GetValue(instance) is Vector2 val2) { val2.y = 0f; property.SetValue(instance, val2); return true; } return false; } private void ResetAdjustmentsIfNeeded() { if (!Plugin.PreserveCameraAdjustments.Value) { heightOffset = 0f; distanceOffset = 0f; } } private void EnsureThirdPersonCamera() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown if ((Object)(object)camera == (Object)null) { return; } if ((Object)(object)thirdPersonCamera != (Object)null) { if (((Behaviour)camera).enabled) { ((Behaviour)camera).enabled = false; } } else { GameObject val = new GameObject("3RdPersonCoeeEX.ThirdPersonCamera"); thirdPersonCamera = val.AddComponent(); thirdPersonCamera.CopyFrom(camera); ((Behaviour)thirdPersonCamera).enabled = true; ((Behaviour)camera).enabled = false; } } private void ShowLocalBody(bool visible) { if (player != null) { SkinnedMeshRenderer fieldOrProperty = GetFieldOrProperty(player, "thisPlayerModel"); if (!((Object)(object)fieldOrProperty == (Object)null)) { ((Renderer)fieldOrProperty).shadowCastingMode = (ShadowCastingMode)((visible || !localBodyWasShadowOnly) ? 1 : 3); } } } private object? GetLocalPlayer() { if ((object)startOfRoundType == null) { startOfRoundType = FindType("StartOfRound"); } if (startOfRoundType == null) { return null; } object staticFieldOrProperty = GetStaticFieldOrProperty(startOfRoundType, "Instance"); if (staticFieldOrProperty != null) { return GetFieldOrProperty(staticFieldOrProperty, "localPlayerController"); } return null; } private static bool IsPlayerDead(object player) { return GetFieldOrProperty(player, "isPlayerDead"); } private static Type? FindType(string typeName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(typeName, throwOnError: false); if (type != null) { return type; } } return null; } private static T? GetStaticFieldOrProperty(Type type, string name) { FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return Cast(field.GetValue(null)); } PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (!(property == null)) { return Cast(property.GetValue(null)); } return default(T); } private static T? GetFieldOrProperty(object instance, string name) { Type type = instance.GetType(); FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return Cast(field.GetValue(instance)); } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(property == null)) { return Cast(property.GetValue(instance)); } return default(T); } private static T? Cast(object? value) { if (value is T) { return (T)value; } return default(T); } } internal static class VanillaButtonSound { private static AudioSource? cachedSource; private static AudioClip? cachedClip; private static float nextSearchTime; public static void Play() { TryRefreshCache(); if ((Object)(object)cachedSource != (Object)null && (Object)(object)cachedClip != (Object)null) { cachedSource.PlayOneShot(cachedClip); return; } AudioSource? obj = cachedSource; if (obj != null) { obj.Play(); } } private static void TryRefreshCache() { if ((!((Object)(object)cachedSource != (Object)null) || !((Object)(object)((Component)cachedSource).gameObject != (Object)null) || !((Component)cachedSource).gameObject.activeInHierarchy || !((Object)(object)cachedClip != (Object)null)) && !(Time.unscaledTime < nextSearchTime)) { nextSearchTime = Time.unscaledTime + 1f; cachedSource = FindMenuAudioSource(); cachedClip = FindLikelyButtonClip(); } } private static AudioSource? FindMenuAudioSource() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) AudioSource[] array = Resources.FindObjectsOfTypeAll(); Scene scene; foreach (AudioSource val in array) { if ((Object)(object)val == (Object)null) { continue; } scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid() && ((Component)val).gameObject.activeInHierarchy) { string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant(); if (text.Contains("menu") || text.Contains("ui") || text.Contains("button")) { return val; } } } array = Resources.FindObjectsOfTypeAll(); foreach (AudioSource val2 in array) { if ((Object)(object)val2 != (Object)null) { scene = ((Component)val2).gameObject.scene; if (((Scene)(ref scene)).IsValid() && ((Component)val2).gameObject.activeInHierarchy) { return val2; } } } return null; } private static AudioClip? FindLikelyButtonClip() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) Component[] array = Resources.FindObjectsOfTypeAll(); Scene scene; foreach (Component val in array) { if ((Object)(object)val == (Object)null) { continue; } scene = val.gameObject.scene; if (((Scene)(ref scene)).IsValid()) { AudioClip val2 = FindClipOnObject(val, "button"); if ((Object)(object)val2 != (Object)null) { return val2; } } } array = Resources.FindObjectsOfTypeAll(); foreach (Component val3 in array) { if ((Object)(object)val3 == (Object)null) { continue; } scene = val3.gameObject.scene; if (((Scene)(ref scene)).IsValid()) { AudioClip val4 = FindClipOnObject(val3, "click"); if ((Object)(object)val4 != (Object)null) { return val4; } } } return null; } private static AudioClip? FindClipOnObject(object instance, string nameHint) { Type type = instance.GetType(); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (typeof(AudioClip).IsAssignableFrom(fieldInfo.FieldType) && fieldInfo.Name.Contains(nameHint, StringComparison.OrdinalIgnoreCase)) { object? value = fieldInfo.GetValue(instance); AudioClip val = (AudioClip)((value is AudioClip) ? value : null); if (val != null) { return val; } } } PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (typeof(AudioClip).IsAssignableFrom(propertyInfo.PropertyType) && propertyInfo.Name.Contains(nameHint, StringComparison.OrdinalIgnoreCase) && propertyInfo.CanRead) { object? value2 = propertyInfo.GetValue(instance); AudioClip val2 = (AudioClip)((value2 is AudioClip) ? value2 : null); if (val2 != null) { return val2; } } } return null; } } }