using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using FirstPersonGB; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Reflection; using MelonLoader; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(FirstPersonGBMod), "FirstPersonGB", "1.2.1", "KMK And Zooks", null)] [assembly: MelonGame("Boneloaf", "Gang Beasts")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("FirstPersonGB")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("First Person for GB")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("FirstPersonGB")] [assembly: AssemblyTitle("FirstPersonGB")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FirstPersonGB { public class FirstPersonGBMod : MelonMod { private bool isFirstPerson; private bool wantsFirstPerson; private string currentSceneName = ""; private float sceneLoadTimer; private float audioScanTimer; private float retrySearchTimer; private Transform playerHead; private Camera mainCamera; private Transform mainCamTransform; private float originalFOV; private float originalNearClip; private float pitch; private float yaw; private readonly float mouseSensitivity = 0.16f; private readonly float controllerSensitivity = 145f; private readonly float positionSmoothSpeed = 48f; private bool justToggled; private Dictionary hiddenRenderers = new Dictionary(); private Dictionary originalUpdateOffscreen = new Dictionary(); private Dictionary originalMeshBounds = new Dictionary(); private List disabledScripts = new List(); private static readonly string[] headKeywords = new string[40] { "actor_head_collider", "actor_head_skinnedMesh", "helper_voiceBox", "head", "skull", "face", "eye", "eyeball", "pupil", "iris", "eyelid", "eyebrow", "brow", "mouth", "lip", "teeth", "tooth", "tongue", "jaw", "chin", "nose", "ear", "hair", "wig", "hat", "cap", "helmet", "helm", "hardhat", "hood", "beanie", "mask", "visor", "glasses", "goggles", "beard", "mustache", "stache", "collar", "neck" }; public override void OnInitializeMelon() { MelonLogger.Msg("FirstPersonGB v1.2.1 P Loaded (Optimized)."); MelonLogger.Msg("Toggle Key: K (Keyboard) or Right-Stick-Click (Controller)."); } public override void OnUpdate() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) try { Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (currentSceneName != name) { MelonLogger.Msg($"[Scene Management] Loading Scene Change: '{currentSceneName}' -> '{name}'"); currentSceneName = name; if (isFirstPerson) { ForceDisableFirstPerson(); } if (wantsFirstPerson) { sceneLoadTimer = 1.5f; } } if (sceneLoadTimer > 0f) { sceneLoadTimer -= Time.deltaTime; if (sceneLoadTimer <= 0f && wantsFirstPerson) { TryEnableFirstPerson(); } } if (wantsFirstPerson && !isFirstPerson && sceneLoadTimer <= 0f) { retrySearchTimer += Time.deltaTime; if (retrySearchTimer >= 0.25f) { retrySearchTimer = 0f; TryEnableFirstPerson(); } } audioScanTimer += Time.deltaTime; if (audioScanTimer >= 1.5f) { audioScanTimer = 0f; ScanAndBoostWarpAudio(); } bool flag = false; if (Keyboard.current != null && ((ButtonControl)Keyboard.current.kKey).wasPressedThisFrame) { flag = true; } if (Gamepad.current != null && Gamepad.current.rightStickButton.wasPressedThisFrame) { flag = true; } if (flag) { if (!isFirstPerson) { wantsFirstPerson = true; TryEnableFirstPerson(); } else { wantsFirstPerson = false; ForceDisableFirstPerson(); } } if (isFirstPerson && ((Object)(object)playerHead == (Object)null || !((Component)playerHead).gameObject.activeInHierarchy)) { MelonLogger.Warning("[FP Safety] Target Lost. Reverting to Third Person."); ForceDisableFirstPerson(); if (wantsFirstPerson) { retrySearchTimer = 0f; } } } catch (Exception value) { MelonLogger.Error($"[OnUpdate Error] Exception: {value}"); } } public override void OnFixedUpdate() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (isFirstPerson && (Object)(object)mainCamTransform != (Object)null) { mainCamTransform.rotation = Quaternion.Euler(pitch, yaw, 0f); } } public override void OnLateUpdate() { if (isFirstPerson) { UpdateVisualCamera(); } } private void ScanAndBoostWarpAudio() { try { AudioSource[] array = Il2CppArrayBase.op_Implicit(Object.FindObjectsOfType()); int num = array.Length; for (int i = 0; i < num; i++) { AudioSource val = array[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val.clip == (Object)null) && ((Object)val.clip).name.IndexOf("Warp 1", StringComparison.OrdinalIgnoreCase) >= 0 && val.volume < 1f) { val.volume = 1f; MelonLogger.Msg($"[Audio Match] Boosted '{((Object)val.clip).name}' on [{((Object)((Component)val).gameObject).name}] to 100% volume."); } } } catch (Exception ex) { MelonLogger.Error("[Audio Error] Scan registry failure: " + ex.Message); } } private void TryEnableFirstPerson() { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) try { mainCamera = Camera.main; if ((Object)(object)mainCamera == (Object)null) { MelonLogger.Error("[FP Mode] Main Camera is null!"); return; } mainCamTransform = ((Component)mainCamera).transform; SmartFindLocalPlayer(); if (!((Object)(object)playerHead == (Object)null)) { MelonLogger.Msg("[FP Mode] Found local actor head '" + ((Object)playerHead).name + "'. Mounting camera..."); originalFOV = mainCamera.fieldOfView; originalNearClip = mainCamera.nearClipPlane; mainCamera.fieldOfView = 125f; mainCamera.nearClipPlane = 0.01f; disabledScripts.Clear(); Transform parent = mainCamTransform; while ((Object)(object)parent != (Object)null) { DisableTrackingScripts(((Component)parent).gameObject); parent = parent.parent; } Quaternion rotation = playerHead.rotation; Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles; yaw = eulerAngles.y; pitch = eulerAngles.x; Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; ApplyHighlyOptimizedRendering(); isFirstPerson = true; justToggled = true; MelonLogger.Msg("[FP Mode] Mounted successfully."); } } catch (Exception value) { MelonLogger.Error($"[FP Mode Error] Activation failure: {value}"); } } private void ForceDisableFirstPerson() { try { isFirstPerson = false; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; RestoreVisibility(); if ((Object)(object)mainCamera != (Object)null) { mainCamera.fieldOfView = originalFOV; mainCamera.nearClipPlane = originalNearClip; int count = disabledScripts.Count; for (int i = 0; i < count; i++) { if ((Object)(object)disabledScripts[i] != (Object)null) { ((Behaviour)disabledScripts[i]).enabled = true; } } } disabledScripts.Clear(); playerHead = null; mainCamTransform = null; MelonLogger.Msg("[FP Mode] Restored system back to Third Person."); } catch (Exception value) { MelonLogger.Error($"[FP Mode Error] Restoration failure: {value}"); } } private void DisableTrackingScripts(GameObject obj) { MonoBehaviour[] array = Il2CppArrayBase.op_Implicit(obj.GetComponents()); int num = array.Length; for (int i = 0; i < num; i++) { MonoBehaviour val = array[i]; if (!((Object)(object)val == (Object)null)) { string text = ((MemberInfo)((Object)val).GetIl2CppType()).Name.ToLower(); if (!text.Contains("postprocess") && !text.Contains("volume") && !text.Contains("amplify") && !text.Contains("layer") && !text.Contains("audio") && ((Behaviour)val).enabled) { ((Behaviour)val).enabled = false; disabledScripts.Add(val); MelonLogger.Msg($"[FP Camera] Disabled camera scripts: {((Object)val).GetIl2CppType().FullName} on [{((Object)obj).name}]"); } } } } private void SmartFindLocalPlayer() { playerHead = null; try { Component[] array = Il2CppArrayBase.op_Implicit(Object.FindObjectsOfType()); Component val = null; int num = array.Length; for (int i = 0; i < num; i++) { Component val2 = array[i]; if ((Object)(object)val2 == (Object)null) { continue; } string name = ((MemberInfo)((Object)val2).GetIl2CppType()).Name; if (!(name == "Actor") && !(name == "ActorCore") && !name.EndsWith(".Actor")) { continue; } Type type = ((object)val2).GetType(); PropertyInfo propertyInfo = type.GetProperty("IsAI") ?? type.GetProperty("isAI"); if (propertyInfo != null) { try { if ((bool)propertyInfo.GetValue(val2, null)) { continue; } } catch { } } PropertyInfo propertyInfo2 = type.GetProperty("isLocalPlayer") ?? type.GetProperty("IsLocal") ?? type.GetProperty("IsLocalPlayer"); if (!(propertyInfo2 != null)) { continue; } try { if ((bool)propertyInfo2.GetValue(val2, null)) { val = val2; break; } } catch { } } if ((Object)(object)val != (Object)null) { Rigidbody[] array2 = Il2CppArrayBase.op_Implicit(((Component)val.transform.root).GetComponentsInChildren(true)); int num2 = array2.Length; for (int j = 0; j < num2; j++) { Rigidbody val3 = array2[j]; if ((Object)(object)val3 != (Object)null && ((Object)((Component)val3).gameObject).name.Equals("actor_head_collider", StringComparison.OrdinalIgnoreCase)) { playerHead = ((Component)val3).transform; return; } } } Rigidbody[] array3 = Il2CppArrayBase.op_Implicit(Object.FindObjectsOfType()); int num3 = array3.Length; for (int k = 0; k < num3; k++) { Rigidbody val4 = array3[k]; if (!((Object)(object)val4 == (Object)null) && ((Object)((Component)val4).gameObject).name.Equals("actor_head_collider", StringComparison.OrdinalIgnoreCase)) { Transform root = ((Component)val4).transform.root; if (((Object)root).name.IndexOf("[PlayerID: 0]", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)root).name.IndexOf("PlayerID: 0", StringComparison.OrdinalIgnoreCase) >= 0) { playerHead = ((Component)val4).transform; break; } } } } catch (Exception ex) { MelonLogger.Error("[SmartFind Error] Local Player discovery failed: " + ex.Message); } } private void ApplyHighlyOptimizedRendering() { //IL_00a2: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) hiddenRenderers.Clear(); originalUpdateOffscreen.Clear(); originalMeshBounds.Clear(); if ((Object)(object)playerHead == (Object)null) { return; } Renderer[] array = Il2CppArrayBase.op_Implicit(((Component)playerHead.root).GetComponentsInChildren(true)); int num = array.Length; for (int i = 0; i < num; i++) { Renderer val = array[i]; if ((Object)(object)val == (Object)null) { continue; } bool flag = false; string name = ((Object)((Component)val).gameObject).name; SkinnedMeshRenderer val2 = ((Il2CppObjectBase)val).TryCast(); if ((Object)(object)val2 != (Object)null) { originalUpdateOffscreen[val2] = val2.updateWhenOffscreen; originalMeshBounds[val2] = ((Renderer)val2).localBounds; val2.updateWhenOffscreen = true; ((Renderer)val2).localBounds = new Bounds(Vector3.zero, Vector3.one * 50f); } if (IsHeadRelated(name)) { flag = true; } if (!flag) { Transform parent = ((Component)val).transform.parent; while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)playerHead.root) { if (IsHeadRelated(((Object)parent).name)) { flag = true; break; } parent = parent.parent; } } if (!flag && (Object)(object)val2 != (Object)null && (Object)(object)val2.sharedMesh != (Object)null && IsHeadRelated(((Object)val2.sharedMesh).name)) { flag = true; } if (flag) { hiddenRenderers[val] = val.enabled; val.enabled = false; MelonLogger.Msg("[Renderer Manager] Completely Hid Head Component: [" + name + "]"); } } } private bool IsHeadRelated(string name) { if (string.IsNullOrEmpty(name)) { return false; } int num = headKeywords.Length; for (int i = 0; i < num; i++) { if (name.IndexOf(headKeywords[i], StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private void RestoreVisibility() { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) try { foreach (KeyValuePair hiddenRenderer in hiddenRenderers) { if ((Object)(object)hiddenRenderer.Key != (Object)null) { hiddenRenderer.Key.enabled = hiddenRenderer.Value; } } hiddenRenderers.Clear(); foreach (KeyValuePair item in originalUpdateOffscreen) { if ((Object)(object)item.Key != (Object)null) { item.Key.updateWhenOffscreen = item.Value; } } originalUpdateOffscreen.Clear(); foreach (KeyValuePair originalMeshBound in originalMeshBounds) { if ((Object)(object)originalMeshBound.Key != (Object)null) { ((Renderer)originalMeshBound.Key).localBounds = originalMeshBound.Value; } } originalMeshBounds.Clear(); MelonLogger.Msg("[FP Mode] Meshes and visibility states completely restored."); } catch (Exception value) { MelonLogger.Error($"[Restoration Error] Reverting pipeline states failed: {value}"); } } private void UpdateVisualCamera() { //IL_002b: 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_0040: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_0170: 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_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) if (!isFirstPerson || (Object)(object)mainCamTransform == (Object)null || (Object)(object)playerHead == (Object)null) { return; } Vector3 val = playerHead.up * 0.48f + playerHead.forward * 0.07f; Vector3 val2 = playerHead.position + val; if (Mouse.current != null) { Vector2 val3 = ((InputControl)(object)((Pointer)Mouse.current).delta).ReadValue(); yaw += val3.x * mouseSensitivity; pitch -= val3.y * mouseSensitivity; } if (Gamepad.current != null) { Vector2 val4 = ((InputControl)(object)Gamepad.current.rightStick).ReadValue(); if (((Vector2)(ref val4)).sqrMagnitude > 0.005f) { yaw += val4.x * controllerSensitivity * Time.deltaTime; pitch -= val4.y * controllerSensitivity * Time.deltaTime; } } pitch = Mathf.Clamp(pitch, -85f, 85f); Quaternion rotation = Quaternion.Euler(pitch, yaw, 0f); if (pitch > 0f) { float num = Mathf.InverseLerp(0f, 85f, pitch); val2 += mainCamTransform.forward * (num * 0.18f); } if (justToggled) { mainCamTransform.position = val2; mainCamTransform.rotation = rotation; justToggled = false; } else { mainCamTransform.position = Vector3.Lerp(mainCamTransform.position, val2, Time.deltaTime * positionSmoothSpeed); mainCamTransform.rotation = rotation; } } } }