Decompiled source of SimpleFreeCam v1.0.0

BepInEx/plugins/SimpleFreeCam.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using SimpleFreeCam.Input;
using SimpleFreeCam.Patches;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SimpleFreeCam")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SimpleFreeCam")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6649931a-a94b-4986-8489-8153ecf188f6")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SimpleFreeCam
{
	internal static class FreeCamClass
	{
		[CompilerGenerated]
		private sealed class <SetupFreecam>d__12 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SetupFreecam>d__12(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitUntil((Func<bool>)(() => (Object)(object)StartOfRound.Instance.localPlayerController != (Object)null));
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					playerController = StartOfRound.Instance.localPlayerController;
					HUDObject = ((Component)GameObject.Find("Systems").transform.Find("Rendering/PlayerHUDHelmetModel")).gameObject;
					playerModel = ((Component)((Component)playerController).transform.Find("ScavengerModel/LOD1")).GetComponent<SkinnedMeshRenderer>();
					mainCameraTransform = ((Component)playerController).transform.Find("ScavengerModel/metarig/CameraContainer/MainCamera");
					freeCameraTransform = GameObject.Find("FreeCameraCinematic").transform;
					FreeCam = StartOfRound.Instance.freeCinematicCamera;
					playerAudioListener = ((Component)playerController).transform.Find("ScavengerModel/metarig/CameraContainer/MainCamera/PlayerAudioListener");
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static GameObject HUDObject;

		private static SkinnedMeshRenderer playerModel;

		private static Transform playerAudioListener;

		private static PlayerControllerB playerController = null;

		internal static bool isInVehicle = false;

		private static Transform mainCameraTransform;

		private static Transform freeCameraTransform;

		private static Camera FreeCam;

		internal static bool lockFreeCam = false;

		internal static bool isInFreeCam = false;

		internal static float freecamSpeed = 3f;

		internal static bool hasBootedAlready = false;

		[IteratorStateMachine(typeof(<SetupFreecam>d__12))]
		public static IEnumerator SetupFreecam()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SetupFreecam>d__12(0);
		}

		public static void SetFreeCamera_performed(CallbackContext obj)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (((CallbackContext)(ref obj)).performed)
			{
				typeof(PlayerControllerB).GetMethod("SetFreeCamera_performed", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(playerController, new object[1] { obj });
				if (isInFreeCam)
				{
					DisableFreecam();
				}
				else if (!playerController.isPlayerDead)
				{
					EnableFreecam();
				}
			}
		}

		public static void ToggleFreecamMovement_performed(CallbackContext obj)
		{
			if (((CallbackContext)(ref obj)).performed && !((Object)(object)playerController == (Object)null) && isInFreeCam)
			{
				lockFreeCam = !lockFreeCam;
				DisableFreecamOnLock();
			}
		}

		public static void SetPlayerController(PlayerControllerB controller)
		{
			playerController = controller;
		}

		public static void SetInVehicle(bool inVehicle)
		{
			isInVehicle = inVehicle;
		}

		private static void EnableFreecam()
		{
			lockFreeCam = false;
			isInFreeCam = true;
			if (SimpleFreeCamPatchBase.instance.FreeCamConfigEntry.Value || !hasBootedAlready)
			{
				hasBootedAlready = true;
				freecamSpeed = SimpleFreeCamPatchBase.instance.FreeCamConfigEntryFloat.Value;
			}
			playerController.isFreeCamera = true;
			StartOfRound.Instance.SwitchCamera(FreeCam);
			HUDObject.SetActive(false);
			((Renderer)playerController.thisPlayerModelArms).enabled = false;
			((Renderer)playerModel).shadowCastingMode = (ShadowCastingMode)1;
			playerAudioListener.SetParent(freeCameraTransform, false);
			HUDManager.Instance.HideHUD(true);
		}

		public static void DisableFreecam()
		{
			lockFreeCam = false;
			isInFreeCam = false;
			playerController.isFreeCamera = false;
			((Behaviour)StartOfRound.Instance.freeCinematicCamera).enabled = false;
			StartOfRound.Instance.SwitchCamera(playerController.isPlayerDead ? StartOfRound.Instance.spectateCamera : playerController.gameplayCamera);
			HUDObject.SetActive(true);
			((Renderer)playerController.thisPlayerModelArms).enabled = true;
			((Renderer)playerModel).shadowCastingMode = (ShadowCastingMode)3;
			playerAudioListener.SetParent(mainCameraTransform, false);
			HUDManager.Instance.HideHUD(playerController.isPlayerDead);
		}

		public static void DisableFreecamOnLock()
		{
			isInFreeCam = true;
			if (lockFreeCam)
			{
				playerController.isFreeCamera = false;
			}
			else
			{
				playerController.isFreeCamera = true;
			}
		}

		internal static void AdjustSpeed(float scrollDelta)
		{
			if (isInFreeCam && !lockFreeCam)
			{
				freecamSpeed = Mathf.Clamp(freecamSpeed + ((scrollDelta > 0f) ? 0.1f : (-0.1f)), 0.1f, 10f);
			}
		}

		internal static float GetSpeed()
		{
			return freecamSpeed;
		}
	}
	internal static class FreeCamSpeedInfo
	{
		internal const float MinSpeed = 0.1f;

		internal const float MaxSpeed = 10f;

		internal const float ScrollStep = 0.1f;

		internal const float DefaultSpeed = 1f;

		internal const float SprintMultiplier = 2f;
	}
	internal static class ModInfo
	{
		internal const string modGUID = "PixelIndieDev_SimpleFreeCam";

		internal const string modName = "Simple Freecam";

		internal const string modVersion = "1.0.0.0";
	}
	[BepInPlugin("PixelIndieDev_SimpleFreeCam", "Simple Freecam", "1.0.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SimpleFreeCamPatchBase : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("PixelIndieDev_SimpleFreeCam");

		public static SimpleFreeCamPatchBase instance;

		internal static SimpleFreeCamInputs InputActionsInstance;

		internal ConfigEntry<bool> FreeCamConfigEntry;

		internal ConfigEntry<float> FreeCamConfigEntryFloat;

		internal ManualLogSource logSource;

		private void Awake()
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_00f9: 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)
			//IL_0110: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			if ((Object)(object)instance == (Object)null)
			{
				instance = this;
			}
			InputActionsInstance = new SimpleFreeCamInputs();
			InputActionsInstance.PixelIndieDev_FreeCamKey.performed += FreeCamClass.SetFreeCamera_performed;
			InputActionsInstance.PixelIndieDev_FreeCamMovementKey.performed += FreeCamClass.ToggleFreecamMovement_performed;
			FreeCamConfigEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Reset speed on freecam", false, "When enabled, the freecam movement speed resets to the default speed every time freecam is activated.");
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(FreeCamConfigEntry, new BoolCheckBoxOptions
			{
				RequiresRestart = false
			}));
			FreeCamConfigEntryFloat = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Default freecam speed", 1f, $"The base movement speed of the freecam. Scroll while in freecam to adjust speed (range: {0.1f} - {10f}, in steps of  {0.1f}).");
			ConfigEntry<float> freeCamConfigEntryFloat = FreeCamConfigEntryFloat;
			FloatStepSliderOptions val = new FloatStepSliderOptions();
			((BaseRangeOptions<float>)val).Min = 0.1f;
			((BaseRangeOptions<float>)val).Max = 10f;
			val.Step = 0.1f;
			((BaseOptions)val).RequiresRestart = false;
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatStepSliderConfigItem(freeCamConfigEntryFloat, val));
			logSource = Logger.CreateLogSource("PixelIndieDev_SimpleFreeCam");
			harmony.PatchAll(typeof(SimpleFreeCamPatchBase));
			harmony.PatchAll(typeof(StartOfRoundPatch));
			harmony.PatchAll(typeof(PlayerControllerPatch));
			harmony.PatchAll(typeof(VehicleControllerPatch));
			harmony.PatchAll(typeof(NetworkPatch));
			logSource.LogInfo((object)"Simple Freecam (version - 1.0.0.0): patches applied successfully");
		}
	}
}
namespace SimpleFreeCam.Patches
{
	[HarmonyPatch(typeof(NetworkManager))]
	internal static class NetworkPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("SetSingleton")]
		private static void RegisterPrefab()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("PixelIndieDev_SimpleFreeCam Prefab");
			((Object)val).hideFlags = (HideFlags)(((Object)val).hideFlags | 0x3D);
			Object.DontDestroyOnLoad((Object)(object)val);
			NetworkObject obj = val.AddComponent<NetworkObject>();
			typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(obj, GetHash("PixelIndieDev_SimpleFreeCam"));
			NetworkManager.Singleton.PrefabHandler.AddNetworkPrefab(val);
		}

		private static uint GetHash(string value)
		{
			return value?.Aggregate(17u, (uint current, char c) => (current * 31) ^ c) ?? 0;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal static class PlayerControllerPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void OnAwake(PlayerControllerB __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner && ((NetworkBehaviour)__instance).IsLocalPlayer)
			{
				FreeCamClass.SetPlayerController(__instance);
			}
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void ApplyFreecamMovement(PlayerControllerB __instance)
		{
			//IL_003b: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: 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_013b: 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)
			if (!((NetworkBehaviour)__instance).IsOwner || !FreeCamClass.isInFreeCam || FreeCamClass.lockFreeCam || FreeCamClass.isInVehicle)
			{
				return;
			}
			Vector2 val = IngamePlayerSettings.Instance.playerInput.actions.FindAction("Move", false).ReadValue<Vector2>();
			float num = IngamePlayerSettings.Instance.playerInput.actions.FindAction("Sprint", false).ReadValue<float>();
			if (!(((Vector2)(ref val)).sqrMagnitude < 0.01f))
			{
				float num2 = FreeCamClass.GetSpeed();
				if (num > 0.5f)
				{
					num2 *= 2f;
				}
				Transform freeCinematicCameraTurnCompass = StartOfRound.Instance.freeCinematicCameraTurnCompass;
				freeCinematicCameraTurnCompass.position += (freeCinematicCameraTurnCompass.right * val.x + freeCinematicCameraTurnCompass.forward * val.y) * num2 * Time.deltaTime;
				((Component)StartOfRound.Instance.freeCinematicCamera).transform.position = Vector3.Lerp(((Component)StartOfRound.Instance.freeCinematicCamera).transform.position, freeCinematicCameraTurnCompass.position, 3f * Time.deltaTime);
				((Component)StartOfRound.Instance.freeCinematicCamera).transform.rotation = Quaternion.Slerp(((Component)StartOfRound.Instance.freeCinematicCamera).transform.rotation, freeCinematicCameraTurnCompass.rotation, 3f * Time.deltaTime);
			}
		}

		[HarmonyPatch("KillPlayer")]
		[HarmonyPostfix]
		private static void OnPlayerDeath(PlayerControllerB __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner && __instance.isFreeCamera)
			{
				FreeCamClass.DisableFreecam();
			}
		}

		[HarmonyPatch("ScrollMouse_performed")]
		[HarmonyPrefix]
		private static bool InterceptScroll(PlayerControllerB __instance, CallbackContext context)
		{
			if (!((NetworkBehaviour)__instance).IsOwner)
			{
				return true;
			}
			if (!FreeCamClass.isInFreeCam)
			{
				return true;
			}
			if (FreeCamClass.lockFreeCam)
			{
				return true;
			}
			FreeCamClass.AdjustSpeed(((CallbackContext)(ref context)).ReadValue<float>());
			return false;
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal static class StartOfRoundPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void OnGameEntered(StartOfRound __instance)
		{
			((MonoBehaviour)__instance).StartCoroutine(FreeCamClass.SetupFreecam());
		}
	}
	[HarmonyPatch(typeof(VehicleController))]
	internal static class VehicleControllerPatch
	{
		[HarmonyPatch("TakeControlOfVehicle")]
		[HarmonyPostfix]
		private static void OnTakeControlOfVehicle(VehicleController __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner && ((NetworkBehaviour)__instance).IsLocalPlayer)
			{
				FreeCamClass.SetInVehicle(inVehicle: true);
			}
		}

		[HarmonyPatch("LoseControlOfVehicle")]
		[HarmonyPostfix]
		private static void OnLoseControlOfVehicle(VehicleController __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner && ((NetworkBehaviour)__instance).IsLocalPlayer)
			{
				FreeCamClass.SetInVehicle(inVehicle: false);
			}
		}

		[HarmonyPatch("GetVehicleInput")]
		[HarmonyPrefix]
		private static bool BlockVehicleInput(VehicleController __instance)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.localPlayerInControl)
			{
				return true;
			}
			if (!FreeCamClass.isInFreeCam)
			{
				return true;
			}
			if (!FreeCamClass.lockFreeCam)
			{
				__instance.moveInputVector = Vector2.zero;
				__instance.drivePedalPressed = false;
				__instance.brakePedalPressed = false;
				return false;
			}
			return true;
		}
	}
}
namespace SimpleFreeCam.Input
{
	public class SimpleFreeCamInputs : LcInputActions
	{
		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction PixelIndieDev_FreeCamKey { get; set; }

		[InputAction(/*Could not decode attribute arguments.*/)]
		public InputAction PixelIndieDev_FreeCamMovementKey { get; set; }
	}
}