diff --git a/project/Terkoiz.Freecam/Freecam.cs b/project/Terkoiz.Freecam/Freecam.cs
index 8125da9..b9d11fc 100644
--- a/project/Terkoiz.Freecam/Freecam.cs
+++ b/project/Terkoiz.Freecam/Freecam.cs
@@ -1,4 +1,5 @@
-using UnityEngine;
+using JetBrains.Annotations;
+using UnityEngine;
 
 namespace Terkoiz.Freecam
 {
@@ -13,7 +14,8 @@ namespace Terkoiz.Freecam
     {
         public bool IsActive = false;
 
-        void Update()
+        [UsedImplicitly]
+        public void Update()
         {
             if (!IsActive)
             {
@@ -43,35 +45,41 @@ namespace Terkoiz.Freecam
                 transform.position += (-transform.forward * movementSpeed * Time.deltaTime);
             }
 
-            if (Input.GetKey(KeyCode.Q))
+            if (FreecamPlugin.CameraHeightMovement.Value)
             {
-                transform.position += (transform.up * movementSpeed * Time.deltaTime);
-            }
+                if (Input.GetKey(KeyCode.Q))
+                {
+                    transform.position += (transform.up * movementSpeed * Time.deltaTime);
+                }
 
-            if (Input.GetKey(KeyCode.E))
-            {
-                transform.position += (-transform.up * movementSpeed * Time.deltaTime);
-            }
+                if (Input.GetKey(KeyCode.E))
+                {
+                    transform.position += (-transform.up * movementSpeed * Time.deltaTime);
+                }
 
-            if (Input.GetKey(KeyCode.R) || Input.GetKey(KeyCode.PageUp))
-            {
-                transform.position += (Vector3.up * movementSpeed * Time.deltaTime);
-            }
+                if (Input.GetKey(KeyCode.R) || Input.GetKey(KeyCode.PageUp))
+                {
+                    transform.position += (Vector3.up * movementSpeed * Time.deltaTime);
+                }
 
-            if (Input.GetKey(KeyCode.F) || Input.GetKey(KeyCode.PageDown))
-            {
-                transform.position += (-Vector3.up * movementSpeed * Time.deltaTime);
+                if (Input.GetKey(KeyCode.F) || Input.GetKey(KeyCode.PageDown))
+                {
+                    transform.position += (-Vector3.up * movementSpeed * Time.deltaTime);
+                }
             }
 
             float newRotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * FreecamPlugin.CameraLookSensitivity.Value;
             float newRotationY = transform.localEulerAngles.x - Input.GetAxis("Mouse Y") * FreecamPlugin.CameraLookSensitivity.Value;
             transform.localEulerAngles = new Vector3(newRotationY, newRotationX, 0f);
 
-            float axis = Input.GetAxis("Mouse ScrollWheel");
-            if (axis != 0)
+            if (FreecamPlugin.CameraMousewheelZoom.Value)
             {
-                var zoomSensitivity = fastMode ? FreecamPlugin.CameraFastZoomSpeed.Value : FreecamPlugin.CameraZoomSpeed.Value;
-                transform.position += transform.forward * axis * zoomSensitivity;
+                float axis = Input.GetAxis("Mouse ScrollWheel");
+                if (axis != 0)
+                {
+                    var zoomSensitivity = fastMode ? FreecamPlugin.CameraFastZoomSpeed.Value : FreecamPlugin.CameraZoomSpeed.Value;
+                    transform.position += transform.forward * axis * zoomSensitivity;
+                }
             }
         }
     }
diff --git a/project/Terkoiz.Freecam/FreecamController.cs b/project/Terkoiz.Freecam/FreecamController.cs
index a2a54e4..e48d1b0 100644
--- a/project/Terkoiz.Freecam/FreecamController.cs
+++ b/project/Terkoiz.Freecam/FreecamController.cs
@@ -1,23 +1,55 @@
-using Comfort.Common;
+using System.Reflection;
+using Comfort.Common;
 using EFT;
+using EFT.CameraControl;
 using EFT.UI;
+using HarmonyLib;
+using JetBrains.Annotations;
+using MonoMod.RuntimeDetour;
 using UnityEngine;
 
 namespace Terkoiz.Freecam
 {
     public class FreecamController : MonoBehaviour
     {
-        private GameObject mainCamera;
-        private Freecam freeCamScript;
+        private GameObject _mainCamera;
+        private Freecam _freeCamScript;
 
-        private BattleUIScreen playerUi;
-        private bool uiHidden;
+        private BattleUIScreen _playerUi;
+        private bool _uiHidden;
 
-        // TODO MAYBE:
-        // Hide player weapon
+        private MethodInfo _playerMoveMethod;
+        private MethodInfo _playerRotateMethod;
+        private Detour _moveDetour;
+        private Detour _rotateDetour;
+
+        private Vector3? _lastPosition;
+        private Quaternion? _lastRotation;
+
+        // TODO:
         // Hide version number UI element
-        // FreeCam controller support (camera could be smoother with an analog stick, apparently)
+        // Button to toggle between camera and player movement
+        // Independent FoV setting for Freecam mode (_mainCamera.GetComponent<Camera>().fieldOfView = ...)
+        
+        [UsedImplicitly]
+        public void Start()
+        {
+            // We locate and get the MethodInfo for the Move method that we will later detour to prevent the player from moving during Freecam
+            _playerMoveMethod = typeof(Player).GetMethod("Move");
+            if (_playerMoveMethod == null)
+            {
+                FreecamPlugin.Logger.LogError("Failed to locate the Player.Move method!");
+            }            
+            
+            // Same deal here, but for player rotation
+            _playerRotateMethod = typeof(Player).GetMethod("Rotate");
+            if (_playerRotateMethod == null)
+            {
+                FreecamPlugin.Logger.LogError("Failed to locate the Player.Rotate method!");
+            }
+        }
 
+        [UsedImplicitly]
         public void Update()
         {
             if (FreecamPlugin.ToggleUi.Value.IsDown())
@@ -49,36 +81,33 @@ namespace Terkoiz.Freecam
             }
 
             // If we don't have the main camera object cached, go look for it in the scene
-            if (mainCamera == null)
+            if (_mainCamera == null)
             {
-                // Finding a GameObject by name directly is apparantly better than searching for objects of a type.
+                // Finding a GameObject by name directly is apparently better than searching for objects of a type.
                 // 'FPS Camera' is our main camera instance - so we just grab that
-                mainCamera = GameObject.Find("FPS Camera");
-                if (mainCamera == null)
+                _mainCamera = GameObject.Find("FPS Camera");
+                if (_mainCamera == null)
                 {
-                    Debug.LogError("Terkoiz.Freecam: ERROR: Failed to locate main camera");
+                    FreecamPlugin.Logger.LogError("Failed to locate main camera");
                     PreloaderUI.Instance.Console.AddLog("ERROR: Failed to locate main camera", "FreeCam");
                     return;
                 }
             }
 
             // Create the Freecam script and attach it to the main camera
-            if (freeCamScript == null)
+            if (_freeCamScript == null)
             {
-                freeCamScript = mainCamera.AddComponent<Freecam>();
+                ClearDetours();
+                _freeCamScript = _mainCamera.AddComponent<Freecam>();
             }
 
-            // We disable the player's GameObject, which prevents the player from moving and interacting with the world while we're in Freecam mode
-            // Also, since the camera position keeps getting updated to where the player is, disabling the player's GameObject also stops this behaviour
-            if (!freeCamScript.IsActive)
+            if (!_freeCamScript.IsActive)
             {
-                localPlayer.gameObject.SetActive(false);
-                freeCamScript.IsActive = true;
+                SetPlayerToFreecamMode(localPlayer);
             }
             else
             {
-                freeCamScript.IsActive = false;
-                localPlayer.gameObject.SetActive(true);
+                SetPlayerToFirstPersonMode(localPlayer);
             }
         }
 
@@ -94,19 +123,19 @@ namespace Terkoiz.Freecam
             }
 
             // If we don't have the main camera cached, it means we have yet to enter Freecam mode and there is nowhere to teleport to
-            if (mainCamera == null)
+            if (_mainCamera == null)
             {
                 return;
             }
 
-            // We basically do what ToggleCamera() does, but with extra code inbetween
-            if (freeCamScript.IsActive)
+            // Move the player to the camera's current position and switch to First Person mode
+            if (_freeCamScript.IsActive)
             {
-                freeCamScript.IsActive = false;
                 // We grab the camera's position, but we subtract a bit off the Y axis, because the players coordinate origin is at the feet
-                var position = new Vector3(mainCamera.transform.position.x, mainCamera.transform.position.y - 1.8f, mainCamera.transform.position.z);
-                localPlayer.gameObject.transform.SetPositionAndRotation(position, mainCamera.transform.rotation);
-                localPlayer.gameObject.SetActive(true);
+                var position = new Vector3(_mainCamera.transform.position.x, _mainCamera.transform.position.y - 1.8f, _mainCamera.transform.position.z);
+                localPlayer.gameObject.transform.SetPositionAndRotation(position, Quaternion.Euler(0, _mainCamera.transform.rotation.y, 0));
+                // localPlayer.gameObject.transform.SetPositionAndRotation(position, _mainCamera.transform.rotation);
+                SetPlayerToFirstPersonMode(localPlayer);
             }
         }
 
@@ -122,26 +151,97 @@ namespace Terkoiz.Freecam
             }
 
             // If we don't have the UI Component cached, go look for it in the scene
-            if (playerUi == null)
+            if (_playerUi == null)
             {
-                playerUi = GameObject.Find("BattleUIScreen").GetComponent<BattleUIScreen>();
+                _playerUi = GameObject.Find("BattleUIScreen").GetComponent<BattleUIScreen>();
 
-                if (playerUi == null)
+                if (_playerUi == null)
                 {
+                    FreecamPlugin.Logger.LogError("Failed to locate player UI");
                     PreloaderUI.Instance.Console.AddLog("ERROR: Failed to locate player UI", "FreeCam");
                     return;
                 }
             }
 
-            playerUi.gameObject.SetActive(uiHidden);
-            uiHidden = !uiHidden;
+            _playerUi.gameObject.SetActive(_uiHidden);
+            _uiHidden = !_uiHidden;
+        }
+
+        /// <summary>
+        /// A helper method to set the Player into Freecam mode
+        /// </summary>
+        /// <param name="localPlayer"></param>
+        private void SetPlayerToFreecamMode(Player localPlayer)
+        {
+            // We set the player to third person mode, but then we want set the camera to freecam mode
+            // This means our character will be fully visible, while letting the camera move freely
+            // Setting the player point of view directly to Freecam seems to hide the head and arms of the character, which is not desirable
+
+            localPlayer.PointOfView = EPointOfView.ThirdPerson;
+
+            // Get the PlayerBody reference. It's a protected field, so we have to use traverse to fetch it
+            var playerBody = Traverse.Create(localPlayer).Field<PlayerBody>("_playerBody").Value;
+            if (playerBody != null)
+            {
+                // We tell the PlayerBody class that it's in FreeCamera mode, and force an update of the Camera Controller view mode
+                // Setting the PointOfView.Value directly skips all the code that would usually change how the player body is rendered
+                playerBody.PointOfView.Value = EPointOfView.FreeCamera;
+                localPlayer.GetComponent<PlayerCameraController>().UpdatePointOfView();
+
+                // All we really needed to do, was trigger the UpdatePointOfView method and have it update to the FreeCam state
+                // There's no easy way of doing this without patching the method, and even then it might be a bloated solution
+            }
+            else
+            {
+                FreecamPlugin.Logger.LogError("Failed to get the PlayerBody field");
+                PreloaderUI.Instance.Console.AddLog("ERROR: Failed to get the PlayerBody field", "FreeCam");
+            }
+
+            // Detour the Player.Move method into an empty one, preventing the character from moving during Freecam mode
+            if (_playerMoveMethod != null)
+            {
+                _moveDetour = new Detour(_playerMoveMethod, typeof(FreecamController).GetMethod(nameof(DisabledMove)));
+            }
+            
+            // Same deal here, but for player rotation
+            if (_playerRotateMethod != null)
+            {
+                _rotateDetour = new Detour(_playerRotateMethod, typeof(FreecamController).GetMethod(nameof(DisabledRotate)));
+            }
+
+            if (FreecamPlugin.CameraRememberLastPosition.Value && _lastPosition != null && _lastRotation != null)
+            {
+                _mainCamera.transform.position = _lastPosition.Value;
+                _mainCamera.transform.rotation = _lastRotation.Value;
+            }
+
+            _freeCamScript.IsActive = true;
+        }
+
+        /// <summary>
+        /// A helper method to reset the player view back to First Person
+        /// </summary>
+        /// <param name="localPlayer"></param>
+        private void SetPlayerToFirstPersonMode(Player localPlayer)
+        {
+            _freeCamScript.IsActive = false;
+
+            if (FreecamPlugin.CameraRememberLastPosition.Value)
+            {
+                _lastPosition = _mainCamera.transform.position;
+                _lastRotation = _mainCamera.transform.rotation;
+            }
+
+            ClearDetours();
+
+            localPlayer.PointOfView = EPointOfView.FirstPerson;
         }
 
         /// <summary>
         /// Gets the current <see cref="Player"/> instance if it's available
         /// </summary>
         /// <returns>Local <see cref="Player"/> instance; returns null if the game is not in raid</returns>
-        private static Player GetLocalPlayerFromWorld()
+        private Player GetLocalPlayerFromWorld()
         {
             // If the GameWorld instance is null or has no RegisteredPlayers, it most likely means we're not in a raid
             var gameWorld = Singleton<GameWorld>.Instance;
@@ -150,8 +250,51 @@ namespace Terkoiz.Freecam
                 return null;
             }
 
-            // One of the RegisterdPlayers will have the IsYourPlayer flag set, which will be our own Player instance
+            // One of the RegisteredPlayers will have the IsYourPlayer flag set, which will be our own Player instance
             return gameWorld.RegisteredPlayers.Find(p => p.IsYourPlayer);
         }
+
+        [UsedImplicitly]
+        public void OnDestroy()
+        {
+            _freeCamScript.IsActive = false;
+
+            // Making sure no stray Detours are left
+            ClearDetours();
+
+            _lastPosition = null;
+            _lastRotation = null;
+        }
+
+        public void ClearDetours()
+        {
+            if (_moveDetour != null)
+            {
+                _moveDetour.Dispose();
+                _moveDetour = null;
+            }
+
+            if (_rotateDetour != null)
+            {
+                _rotateDetour.Dispose();
+                _rotateDetour = null;
+            }
+        }
+
+        /// <summary>
+        /// An empty method that's used to detour the player Move method, preventing movement during Freecam mode
+        /// </summary>
+        [UsedImplicitly]
+        public static void DisabledMove(Player self, Vector2 direction)
+        {
+        }
+
+        /// <summary>
+        /// An empty method that's used to detour the player Rotate method, preventing rotation during Freecam mode
+        /// </summary>
+        [UsedImplicitly]
+        public static void DisabledRotate(Player self, Vector2 deltaRotation, bool ignoreClamp = false)
+        {
+        }
     }
 }
\ No newline at end of file
diff --git a/project/Terkoiz.Freecam/FreecamPlugin.cs b/project/Terkoiz.Freecam/FreecamPlugin.cs
index 389835d..1127c4b 100644
--- a/project/Terkoiz.Freecam/FreecamPlugin.cs
+++ b/project/Terkoiz.Freecam/FreecamPlugin.cs
@@ -1,12 +1,16 @@
 using BepInEx;
 using BepInEx.Configuration;
+using BepInEx.Logging;
+using JetBrains.Annotations;
 using UnityEngine;
 
 namespace Terkoiz.Freecam
 {
-    [BepInPlugin("com.terkoiz.freecam", "Terkoiz.Freecam", "1.1.1")]
+    [BepInPlugin("com.terkoiz.freecam", "Terkoiz.Freecam", "1.2.0")]
     public class FreecamPlugin : BaseUnityPlugin
     {
+        internal new static ManualLogSource Logger { get; private set; }
+
         private static GameObject HookObject;
 
         // Keyboard shortcut config entries
@@ -23,13 +27,23 @@ namespace Terkoiz.Freecam
         internal static ConfigEntry<float> CameraZoomSpeed;
         internal static ConfigEntry<float> CameraFastZoomSpeed;
 
-        private void Awake()
+        private const string TogglesSectionName = "Toggles";
+        internal static ConfigEntry<bool> CameraHeightMovement;
+        internal static ConfigEntry<bool> CameraMousewheelZoom;
+        internal static ConfigEntry<bool> CameraRememberLastPosition;
+
+        // TODO: Hook into camera OnDestroy to run the OnDestroy from FreecamController
+
+        [UsedImplicitly]
+        internal void Start()
         {
+            Logger = base.Logger;
+
             InitConfiguration();
 
             HookObject = new GameObject();
             HookObject.AddComponent<FreecamController>();
-            Object.DontDestroyOnLoad(HookObject);
+            DontDestroyOnLoad(HookObject);
         }
 
         private void InitConfiguration()
@@ -91,6 +105,25 @@ namespace Terkoiz.Freecam
                 new ConfigDescription(
                     "Amount to zoom the camera when using the mouse wheel while holding Shift",
                     new AcceptableValueRange<float>(0.01f, 1000f)));
+
+            CameraHeightMovement = Config.Bind(
+                TogglesSectionName,
+                "CameraHeightMovementKeys",
+                true,
+                "Enables or disables the camera height movement keys, which default to Q, E, R, F." + 
+                " \nUseful to disable if you want to let your character lean in Freecam mode");
+
+            CameraMousewheelZoom = Config.Bind(
+                TogglesSectionName,
+                "CameraMousewheelZoom",
+                true,
+                "Enables or disables camera movement on mousewheel scroll. Just in case you find it annoying.");
+
+            CameraRememberLastPosition = Config.Bind(
+                TogglesSectionName,
+                "CameraRememberLastPosition",
+                false,
+                "If enabled, returning to Freecam mode will put the camera to it's last position which was saved when exiting Freecam mode.");
         }
     }
 }
diff --git a/project/Terkoiz.Freecam/Terkoiz.Freecam.csproj b/project/Terkoiz.Freecam/Terkoiz.Freecam.csproj
index b28ec79..04b8d39 100644
--- a/project/Terkoiz.Freecam/Terkoiz.Freecam.csproj
+++ b/project/Terkoiz.Freecam/Terkoiz.Freecam.csproj
@@ -13,6 +13,8 @@
     <FileAlignment>512</FileAlignment>
     <Deterministic>true</Deterministic>
     <TargetFrameworkProfile />
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -39,11 +41,14 @@
     </AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="0Harmony, Version=2.7.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\HarmonyX.2.7.0\lib\net45\0Harmony.dll</HintPath>
+    </Reference>
     <Reference Include="Assembly-CSharp">
       <HintPath>..\Shared\Hollowed\Assembly-CSharp.dll</HintPath>
     </Reference>
-    <Reference Include="BepInEx, Version=5.4.17.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\BepInEx.BaseLib.5.4.17\lib\net35\BepInEx.dll</HintPath>
+    <Reference Include="BepInEx, Version=5.4.19.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\BepInEx.BaseLib.5.4.19\lib\net35\BepInEx.dll</HintPath>
     </Reference>
     <Reference Include="Comfort">
       <HintPath>..\Shared\Managed\Comfort.dll</HintPath>
@@ -51,6 +56,24 @@
     <Reference Include="ItemComponent.Types">
       <HintPath>..\Shared\Managed\ItemComponent.Types.dll</HintPath>
     </Reference>
+    <Reference Include="Mono.Cecil, Version=0.11.4.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
+      <HintPath>..\packages\Mono.Cecil.0.11.4\lib\net40\Mono.Cecil.dll</HintPath>
+    </Reference>
+    <Reference Include="Mono.Cecil.Mdb, Version=0.11.4.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
+      <HintPath>..\packages\Mono.Cecil.0.11.4\lib\net40\Mono.Cecil.Mdb.dll</HintPath>
+    </Reference>
+    <Reference Include="Mono.Cecil.Pdb, Version=0.11.4.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
+      <HintPath>..\packages\Mono.Cecil.0.11.4\lib\net40\Mono.Cecil.Pdb.dll</HintPath>
+    </Reference>
+    <Reference Include="Mono.Cecil.Rocks, Version=0.11.4.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
+      <HintPath>..\packages\Mono.Cecil.0.11.4\lib\net40\Mono.Cecil.Rocks.dll</HintPath>
+    </Reference>
+    <Reference Include="MonoMod.RuntimeDetour, Version=21.12.13.1, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\MonoMod.RuntimeDetour.21.12.13.1\lib\net452\MonoMod.RuntimeDetour.dll</HintPath>
+    </Reference>
+    <Reference Include="MonoMod.Utils, Version=21.12.13.1, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\MonoMod.Utils.21.12.13.1\lib\net452\MonoMod.Utils.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="UnityEngine">
       <HintPath>..\Shared\Managed\UnityEngine.dll</HintPath>
@@ -76,4 +99,11 @@
     <None Include="packages.config" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\packages\BepInEx.Core.5.4.19\build\BepInEx.Core.targets" Condition="Exists('..\packages\BepInEx.Core.5.4.19\build\BepInEx.Core.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\packages\BepInEx.Core.5.4.19\build\BepInEx.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\BepInEx.Core.5.4.19\build\BepInEx.Core.targets'))" />
+  </Target>
 </Project>
\ No newline at end of file
diff --git a/project/Terkoiz.Freecam/packages.config b/project/Terkoiz.Freecam/packages.config
index 14409c9..47859cc 100644
--- a/project/Terkoiz.Freecam/packages.config
+++ b/project/Terkoiz.Freecam/packages.config
@@ -1,4 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="BepInEx.BaseLib" version="5.4.17" targetFramework="net472" />
+  <package id="BepInEx.BaseLib" version="5.4.19" targetFramework="net472" />
+  <package id="BepInEx.Core" version="5.4.19" targetFramework="net472" />
+  <package id="HarmonyX" version="2.7.0" targetFramework="net472" />
+  <package id="Mono.Cecil" version="0.11.4" targetFramework="net472" />
+  <package id="MonoMod.RuntimeDetour" version="21.12.13.1" targetFramework="net472" />
+  <package id="MonoMod.Utils" version="21.12.13.1" targetFramework="net472" />
 </packages>
\ No newline at end of file