Decompiled source of FirstPersonPOV v1.1.2

M4GMaRFirstPersonCamera.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("M4GMaRFirstPersonCamera")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("M4GMaRFirstPersonCamera")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c03b480e-ea29-4d74-80a9-f836145f9834")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FirstPersonCamera;

[BepInPlugin("com.m4gmar.firstPersonCamera", "First Person Camera Mod", "1.1.2")]
public class FirstPersonCamera : BaseUnityPlugin
{
	[Tooltip("Mouse X sensitivity multiplier")]
	[SerializeField]
	private float sensitivityX = 1f;

	[Tooltip("Mouse Y sensitivity multiplier")]
	[SerializeField]
	private float sensitivityY = 1f;

	public bool useFirstPersonMod = true;

	public bool usePaniniProjection = true;

	public bool useDynamicPanini = true;

	public float paniniMultiplier = 1f;

	public float FOV = 100f;

	private ConfigEntry<bool> configUsePaniniProjection;

	private ConfigEntry<bool> configUseDynamicPanini;

	private ConfigEntry<float> configPaniniMultiplier;

	private ConfigEntry<float> configFOV;

	private bool initializationRequested = false;

	private Camera mainCamera;

	private GameObject primaryCharacter;

	private GameObject secondaryCharacter;

	private Transform primaryHeadTransform;

	private Transform secondaryHeadTransform;

	private PlayerHealth primaryCharacterHealth;

	private Quaternion lastHeadRotation = Quaternion.identity;

	private float pitch = 0f;

	private float yaw = 0f;

	private PaniniProjection panini;

	private PlayerOptionsManager POM;

	private Coroutine secondaryCharacterUpdaterCoroutine;

	private InputAction toggleMenuAction;

	private bool showMenu = false;

	private void Awake()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Expected O, but got Unknown
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Expected O, but got Unknown
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Expected O, but got Unknown
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Expected O, but got Unknown
		((BaseUnityPlugin)this).Logger.LogInfo((object)"AWAKE: Hooking into SceneManager.sceneLoaded");
		configUsePaniniProjection = ((BaseUnityPlugin)this).Config.Bind<bool>("Panini", "UsePaniniProjection", true, new ConfigDescription("If true, Panini projection (lens correction) will be created and applied at runtime.", (AcceptableValueBase)null, Array.Empty<object>()));
		configUseDynamicPanini = ((BaseUnityPlugin)this).Config.Bind<bool>("Panini", "UseDynamicPanini", true, new ConfigDescription("If true, Panini distance will be updated dynamically based on camera vertical direction.", (AcceptableValueBase)null, Array.Empty<object>()));
		configPaniniMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Panini", "PaniniMultiplier", 1f, new ConfigDescription("Base multiplier for the Panini projection distance.", (AcceptableValueBase)null, Array.Empty<object>()));
		configFOV = ((BaseUnityPlugin)this).Config.Bind<float>("Panini", "FOV", 100f, new ConfigDescription("Base FOV for the camera.", (AcceptableValueBase)null, Array.Empty<object>()));
		LoadConfig();
		SceneManager.sceneLoaded += OnSceneLoaded;
		toggleMenuAction = new InputAction("ToggleMenu", (InputActionType)1, "<Keyboard>/f8", (string)null, (string)null, (string)null);
		toggleMenuAction.performed += delegate
		{
			showMenu = !showMenu;
		};
		toggleMenuAction.Enable();
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
		if (secondaryCharacterUpdaterCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(secondaryCharacterUpdaterCoroutine);
			secondaryCharacterUpdaterCoroutine = null;
		}
		if (toggleMenuAction == null)
		{
			return;
		}
		toggleMenuAction.Disable();
		try
		{
			toggleMenuAction.performed -= delegate
			{
				showMenu = !showMenu;
			};
		}
		catch
		{
		}
		toggleMenuAction.Dispose();
		toggleMenuAction = null;
	}

	private void LoadConfig()
	{
		usePaniniProjection = configUsePaniniProjection.Value;
		useDynamicPanini = configUseDynamicPanini.Value;
		paniniMultiplier = configPaniniMultiplier.Value;
		FOV = configFOV.Value;
		ApplyPaniniSettings();
	}

	private void SaveConfig()
	{
		configUsePaniniProjection.Value = usePaniniProjection;
		configUseDynamicPanini.Value = useDynamicPanini;
		configPaniniMultiplier.Value = paniniMultiplier;
		configFOV.Value = FOV;
		((BaseUnityPlugin)this).Config.Save();
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"Config saved: usePaniniProjection={usePaniniProjection} useDynamicPanini={useDynamicPanini} paniniMultiplier={paniniMultiplier}");
		ApplyPaniniSettings();
	}

	private void ApplyPaniniSettings()
	{
		if ((Object)(object)panini != (Object)null)
		{
			((VolumeComponent)panini).active = usePaniniProjection;
			((VolumeParameter)panini.distance).overrideState = true;
			((VolumeParameter<float>)(object)panini.distance).value = paniniMultiplier;
			((VolumeParameter)panini.cropToFit).overrideState = true;
			((VolumeParameter<float>)(object)panini.cropToFit).value = 1f;
		}
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)("SCENE LOADED: " + ((Scene)(ref scene)).name));
		if (((Scene)(ref scene)).name.Contains("map") && useFirstPersonMod)
		{
			initializationRequested = true;
		}
	}

	private void LateUpdate()
	{
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		if (initializationRequested)
		{
			initializationRequested = false;
			((MonoBehaviour)this).StartCoroutine(InitializeCharacterReferencesAsync());
		}
		if ((Object)(object)mainCamera != (Object)null && (Object)(object)primaryHeadTransform != (Object)null && (Object)(object)primaryCharacterHealth != (Object)null && primaryCharacterHealth.alive)
		{
			UpdateCameraRotation();
			UpdateCameraPosition();
			PlayerInputManager val = Object.FindFirstObjectByType<PlayerInputManager>();
			if ((Object)(object)val != (Object)null)
			{
				val.rotatePlayer.targetRotation = ((Component)mainCamera).transform.eulerAngles.y;
			}
			if ((Object)(object)POM == (Object)null)
			{
				POM = Object.FindFirstObjectByType<PlayerOptionsManager>();
			}
			if ((Object)(object)POM != (Object)null)
			{
				mainCamera.fieldOfView = POM.cameraFOV.value;
				FOV = POM.cameraFOV.value;
			}
			if ((Object)(object)panini != (Object)null && useDynamicPanini)
			{
				Vector3 forward = ((Component)mainCamera).transform.forward;
				float y = forward.y;
				((VolumeParameter<float>)(object)panini.distance).value = Mathf.Clamp01(1f - Mathf.Abs(y)) * paniniMultiplier;
			}
			if ((Object)(object)panini != (Object)null && !useDynamicPanini)
			{
				((VolumeParameter<float>)(object)panini.distance).value = paniniMultiplier;
			}
			if ((Object)(object)panini != (Object)null && !usePaniniProjection)
			{
				((VolumeParameter<float>)(object)panini.distance).value = 0f;
			}
		}
		if (!((Object)(object)primaryCharacterHealth != (Object)null) || primaryCharacterHealth.alive || !((Object)(object)primaryHeadTransform != (Object)null))
		{
			return;
		}
		MeshRenderer[] componentsInChildren = ((Component)primaryHeadTransform).gameObject.GetComponentsInChildren<MeshRenderer>();
		MeshRenderer[] array = componentsInChildren;
		foreach (MeshRenderer val2 in array)
		{
			if (!((Renderer)val2).enabled)
			{
				((Renderer)val2).enabled = true;
			}
		}
	}

	private IEnumerator InitializeCharacterReferencesAsync()
	{
		yield return (object)new WaitForSeconds(1f);
		CacheMainCameraAndPrimaryCharacter();
		if ((Object)(object)mainCamera != (Object)null)
		{
			mainCamera.targetTexture = null;
		}
		if (secondaryCharacterUpdaterCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(secondaryCharacterUpdaterCoroutine);
		}
		secondaryCharacterUpdaterCoroutine = ((MonoBehaviour)this).StartCoroutine(PeriodicSecondaryCharacterSearch());
		POM = Object.FindFirstObjectByType<PlayerOptionsManager>((FindObjectsInactive)1);
		if (usePaniniProjection)
		{
			GameObject volumeGO = new GameObject("Runtime Panini+Lens Volume");
			Volume volume = volumeGO.AddComponent<Volume>();
			volume.isGlobal = true;
			VolumeProfile profile = (volume.profile = ScriptableObject.CreateInstance<VolumeProfile>());
			PaniniProjection panini = default(PaniniProjection);
			if (!profile.TryGet<PaniniProjection>(ref panini))
			{
				panini = profile.Add<PaniniProjection>(true);
			}
			((VolumeComponent)panini).active = usePaniniProjection;
			((VolumeParameter)panini.distance).overrideState = true;
			((VolumeParameter<float>)(object)panini.distance).value = paniniMultiplier;
			((VolumeParameter)panini.cropToFit).overrideState = true;
			((VolumeParameter<float>)(object)panini.cropToFit).value = 1f;
			this.panini = panini;
		}
	}

	private void CacheMainCameraAndPrimaryCharacter()
	{
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		mainCamera = Camera.main;
		if ((Object)(object)mainCamera == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"No main camera found.");
			return;
		}
		mainCamera.fieldOfView = FOV;
		primaryCharacter = FindClosestCharacterToCamera();
		if ((Object)(object)primaryCharacter == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"No characters found in the scene.");
			return;
		}
		primaryHeadTransform = FindHeadTransformInChildren(primaryCharacter);
		if ((Object)(object)primaryHeadTransform != (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Cached " + ((Object)primaryCharacter).name + "'s head transform."));
			DestroyCameraSmoothFollowComponents();
			lastHeadRotation = primaryHeadTransform.rotation;
			primaryCharacterHealth = primaryCharacter.GetComponent<PlayerHealth>();
			MeshRenderer[] componentsInChildren = ((Component)primaryHeadTransform).gameObject.GetComponentsInChildren<MeshRenderer>();
			MeshRenderer[] array = componentsInChildren;
			foreach (MeshRenderer val in array)
			{
				((Renderer)val).enabled = false;
			}
		}
		else
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("No 'head' (neck) component found in " + ((Object)primaryCharacter).name + "."));
		}
	}

	private GameObject FindClosestCharacterToCamera()
	{
		//IL_0046: 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)
		GameObject[] array = Object.FindObjectsByType<GameObject>((FindObjectsSortMode)0);
		GameObject val = null;
		float num = float.MaxValue;
		GameObject[] array2 = array;
		foreach (GameObject val2 in array2)
		{
			if (((Object)val2).name.Contains("Character"))
			{
				float num2 = Vector3.Distance(((Component)mainCamera).transform.position, val2.transform.position);
				if (num2 < num)
				{
					num = num2;
					val = val2;
				}
			}
		}
		if ((Object)(object)val != (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Closest character cached: " + ((Object)val).name));
			primaryCharacterHealth = val.GetComponent<PlayerHealth>();
		}
		return val;
	}

	private Transform FindHeadTransformInChildren(GameObject character)
	{
		if ((Object)(object)character == (Object)null)
		{
			return null;
		}
		Transform[] componentsInChildren = character.GetComponentsInChildren<Transform>(true);
		Transform[] array = componentsInChildren;
		foreach (Transform val in array)
		{
			if (((Object)val).name.IndexOf("neck", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return val;
			}
		}
		return null;
	}

	private void DestroyCameraSmoothFollowComponents()
	{
		CameraSmoothFollow[] array = Object.FindObjectsByType<CameraSmoothFollow>((FindObjectsSortMode)0);
		CameraSmoothFollow[] array2 = array;
		foreach (CameraSmoothFollow val in array2)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Found CameraSmoothFollow in " + ((Object)((Component)val).gameObject).name + " ...DESTROYING IT and relocating Camera"));
			Object.Destroy((Object)(object)val);
		}
	}

	private void UpdateCameraPosition()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		((Component)mainCamera).gameObject.transform.position = primaryHeadTransform.TransformPoint(0f, 0.12f, 0.04f);
		mainCamera.nearClipPlane = 0.06f;
	}

	private IEnumerator PeriodicSecondaryCharacterSearch()
	{
		while (true)
		{
			if ((Object)(object)primaryCharacter != (Object)null)
			{
				secondaryCharacter = FindSecondClosestLivingCharacter();
				if ((Object)(object)secondaryCharacter != (Object)null)
				{
					secondaryHeadTransform = FindHeadTransformInChildren(secondaryCharacter);
					if ((Object)(object)secondaryHeadTransform != (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Second closest character's head cached: " + ((Object)secondaryHeadTransform).name));
					}
					else
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("No 'head' (neck) component found in " + ((Object)secondaryCharacter).name + "."));
					}
				}
			}
			yield return (object)new WaitForSeconds(2f);
		}
	}

	private GameObject FindSecondClosestLivingCharacter()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		GameObject[] array = Object.FindObjectsByType<GameObject>((FindObjectsSortMode)0);
		GameObject val = null;
		float num = float.MaxValue;
		GameObject[] array2 = array;
		foreach (GameObject val2 in array2)
		{
			if (!((Object)val2).name.Contains("Character") || (Object)(object)val2 == (Object)(object)primaryCharacter)
			{
				continue;
			}
			float num2 = Vector3.Distance(((Component)mainCamera).transform.position, val2.transform.position);
			if (num2 < num)
			{
				PlayerHealth component = val2.GetComponent<PlayerHealth>();
				if ((Object)(object)component != (Object)null && component.alive)
				{
					num = num2;
					val = val2;
				}
			}
		}
		if ((Object)(object)val != (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Second closest character cached: " + ((Object)val).name));
		}
		return val;
	}

	private void UpdateCameraRotation()
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: 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_006b: 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_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: 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_01d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: 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_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_02af: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: 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_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: 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_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)primaryCharacter == (Object)null || (Object)(object)primaryHeadTransform == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Character or Head transform is missing.");
			return;
		}
		Vector3 forward = primaryHeadTransform.forward;
		Quaternion val = primaryHeadTransform.rotation * Quaternion.Euler(10f, 0f, 0f);
		float num = 4000f;
		float num2 = 4000f;
		Vector3 zero = Vector3.zero;
		if (Keyboard.current != null)
		{
			if (((ButtonControl)Keyboard.current.eKey).isPressed)
			{
				zero.y += num * Time.deltaTime;
			}
			if (((ButtonControl)Keyboard.current.qKey).isPressed)
			{
				zero.y -= num * Time.deltaTime;
			}
			if (((ButtonControl)Keyboard.current.rKey).isPressed)
			{
				zero.x -= num2 * Time.deltaTime;
			}
			if (((ButtonControl)Keyboard.current.fKey).isPressed)
			{
				zero.x += num2 * Time.deltaTime;
			}
		}
		if ((Object)(object)secondaryCharacter != (Object)null && (Object)(object)secondaryHeadTransform != (Object)null)
		{
			Vector3 val2 = secondaryHeadTransform.position - ((Component)mainCamera).transform.position;
			Vector3 normalized = ((Vector3)(ref val2)).normalized;
			float num3 = Vector3.Angle(forward, normalized);
			if (num3 <= 100f)
			{
				val2 = Vector3.Lerp(forward, normalized, 0.32f);
				Vector3 normalized2 = ((Vector3)(ref val2)).normalized;
				val = Quaternion.LookRotation(normalized2);
			}
			else
			{
				val = primaryHeadTransform.rotation;
			}
		}
		Quaternion val3 = Quaternion.Euler(zero);
		val *= val3;
		if (Mouse.current != null)
		{
			Vector2 val4 = ((InputControl<Vector2>)(object)((Pointer)Mouse.current).delta).ReadValue();
			yaw += val4.x * sensitivityX;
			pitch -= val4.y * sensitivityY;
			pitch = Mathf.Clamp(pitch, -64f, 64f);
			yaw = Mathf.Clamp(yaw, -64f, 64f);
			yaw = Mathf.Lerp(yaw, 0f, 1f * Time.deltaTime);
			pitch = Mathf.Lerp(pitch, 0f, 1f * Time.deltaTime);
			val *= Quaternion.Euler(pitch, yaw, 0f);
		}
		((Component)mainCamera).transform.rotation = Quaternion.Slerp(((Component)mainCamera).transform.rotation, val, 2f * Time.deltaTime);
	}

	private void OnGUI()
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: 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_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: 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_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_02df: Unknown result type (might be due to invalid IL or missing references)
		if (showMenu)
		{
			int num = 800;
			int num2 = 400;
			int num3 = 420;
			int num4 = 200;
			GUI.Box(new Rect((float)num - 10f, (float)num2 - 10f, (float)(num3 + 20), (float)(num4 + 160)), "First Person Camera Config");
			int num5 = num;
			int num6 = num2;
			num6 += 50;
			GUI.Label(new Rect((float)num5, (float)num6, 380f, 20f), "Enable First Person");
			useFirstPersonMod = GUI.Toggle(new Rect((float)num5, (float)(num6 + 20), 380f, 20f), useFirstPersonMod, $"{useFirstPersonMod}");
			num6 += 50;
			GUI.Label(new Rect((float)num5, (float)num6, 380f, 20f), "Use Panini Projection");
			usePaniniProjection = GUI.Toggle(new Rect((float)num5, (float)(num6 + 20), 380f, 20f), usePaniniProjection, $"{usePaniniProjection}");
			num6 += 50;
			GUI.Label(new Rect((float)num5, (float)num6, 380f, 20f), "Use Dynamic Panini");
			useDynamicPanini = GUI.Toggle(new Rect((float)num5, (float)(num6 + 20), 380f, 20f), useDynamicPanini, $"{useDynamicPanini}");
			num6 += 50;
			GUI.Label(new Rect((float)num5, (float)num6, 380f, 20f), $"Panini Multiplier: {paniniMultiplier:F2}");
			paniniMultiplier = GUI.HorizontalSlider(new Rect((float)num5, (float)(num6 + 20), 260f, 20f), paniniMultiplier, 0f, 1f);
			string s = GUI.TextField(new Rect((float)(num5 + 270), (float)(num6 + 18), 90f, 22f), paniniMultiplier.ToString("F2"));
			if (float.TryParse(s, out var result))
			{
				paniniMultiplier = result;
			}
			num6 += 60;
			if (GUI.Button(new Rect((float)num5, (float)num6, 130f, 32f), "Apply & Save"))
			{
				SaveConfig();
			}
			if (GUI.Button(new Rect((float)(num5 + 150), (float)num6, 140f, 32f), "Reset to Default"))
			{
				usePaniniProjection = true;
				useDynamicPanini = true;
				paniniMultiplier = 1f;
				SaveConfig();
			}
			if (GUI.Button(new Rect((float)(num5 + 305), (float)num6, 120f, 32f), "Restore Config"))
			{
				LoadConfig();
			}
		}
	}
}