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 3RdPersonCoeeEX v1.0.0
BepInEx\plugins\3RdPersonCoeeEX.dll
Decompiled 16 hours agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using 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<CameraSwitchingMethod> 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<Component>(); 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<object>())); 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<CameraSwitchingMethod> SwitchingMethod; internal static ConfigEntry<bool> ShowInGameSettings; internal static ConfigEntry<bool> 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<CameraSwitchingMethod>("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<bool>("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<bool>("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<ThirdPersonCameraController>(); val.AddComponent<InGameCameraSettingsMenu>(); ((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<Camera>(localPlayer, "gameplayCamera"); if (!((Object)(object)camera == (Object)null)) { cameraCaptured = true; thirdPersonActive = false; wheelDistance = 0f; toggleView = ToggleView.FirstPerson; SkinnedMeshRenderer fieldOrProperty = GetFieldOrProperty<SkinnedMeshRenderer>(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<Camera>(); thirdPersonCamera.CopyFrom(camera); ((Behaviour)thirdPersonCamera).enabled = true; ((Behaviour)camera).enabled = false; } } private void ShowLocalBody(bool visible) { if (player != null) { SkinnedMeshRenderer fieldOrProperty = GetFieldOrProperty<SkinnedMeshRenderer>(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<object>(startOfRoundType, "Instance"); if (staticFieldOrProperty != null) { return GetFieldOrProperty<object>(staticFieldOrProperty, "localPlayerController"); } return null; } private static bool IsPlayerDead(object player) { return GetFieldOrProperty<bool>(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<T>(Type type, string name) { FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return Cast<T>(field.GetValue(null)); } PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (!(property == null)) { return Cast<T>(property.GetValue(null)); } return default(T); } private static T? GetFieldOrProperty<T>(object instance, string name) { Type type = instance.GetType(); FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return Cast<T>(field.GetValue(instance)); } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(property == null)) { return Cast<T>(property.GetValue(instance)); } return default(T); } private static T? Cast<T>(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<AudioSource>(); 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<AudioSource>(); 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<Component>(); 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<Component>(); 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; } } }