diff --git a/DesktopVRSwitch/DesktopVRSwitch.csproj b/DesktopVRSwitch/DesktopVRSwitch.csproj
new file mode 100644
index 0000000..2251ad3
--- /dev/null
+++ b/DesktopVRSwitch/DesktopVRSwitch.csproj
@@ -0,0 +1,61 @@
+
+
+
+
+ net472
+ enable
+ latest
+ false
+
+
+
+
+ C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\MelonLoader\0Harmony.dll
+
+
+ C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll
+
+
+ ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll
+
+
+ ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll
+
+
+ ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll
+
+
+ ..\..\Giamoz\Giamoz\bin\Debug\net472\Giamoz.dll
+
+
+ C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\MelonLoader\MelonLoader.dll
+
+
+ C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\SteamVR.dll
+
+
+ ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll
+
+
+ C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll
+
+
+ C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.InputLegacyModule.dll
+
+
+ ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.PhysicsModule.dll
+
+
+ ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.VRModule.dll
+
+
+ ..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.XRModule.dll
+
+
+
+
+
+
+
+
+
diff --git a/DesktopVRSwitch/DesktopVRSwitch.sln b/DesktopVRSwitch/DesktopVRSwitch.sln
new file mode 100644
index 0000000..758488c
--- /dev/null
+++ b/DesktopVRSwitch/DesktopVRSwitch.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.2.32630.192
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DesktopVRSwitch", "DesktopVRSwitch.csproj", "{4008E6D1-32F9-449B-8820-80ACF0ED8233}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4008E6D1-32F9-449B-8820-80ACF0ED8233}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4008E6D1-32F9-449B-8820-80ACF0ED8233}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4008E6D1-32F9-449B-8820-80ACF0ED8233}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4008E6D1-32F9-449B-8820-80ACF0ED8233}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {3C86465A-87F5-49EF-915C-5B5F568A8815}
+ EndGlobalSection
+EndGlobal
diff --git a/DesktopVRSwitch/Main.cs b/DesktopVRSwitch/Main.cs
new file mode 100644
index 0000000..548df04
--- /dev/null
+++ b/DesktopVRSwitch/Main.cs
@@ -0,0 +1,181 @@
+using HarmonyLib;
+using MelonLoader;
+using UnityEngine;
+using RootMotion.FinalIK;
+using ABI_RC.Core.Player;
+using ABI_RC.Core.Savior;
+using ABI.CCK.Components;
+using ABI_RC.Core.InteractionSystem;
+using ABI_RC.Systems.MovementSystem;
+using ABI_RC.Core.UI;
+using System.Reflection;
+using cohtml;
+using ABI_RC.Core.IO;
+using System.Collections;
+using System;
+using UnityEngine.XR;
+using Valve.VR;
+
+namespace DesktopVRSwitch;
+
+public class DesktopVRSwitch : MelonMod
+{
+
+ private static MelonPreferences_Category m_categoryDesktopVRSwitch;
+ private static MelonPreferences_Entry m_entryEnabled;
+
+ private static System.Object melon;
+
+ public override void OnApplicationStart()
+ {
+ m_categoryDesktopVRSwitch = MelonPreferences.CreateCategory(nameof(DesktopVRSwitch));
+ m_entryEnabled = m_categoryDesktopVRSwitch.CreateEntry("Start SteamVR", false, description: "Launch SteamVR");
+ m_entryEnabled.OnValueChangedUntyped += UpdateSettings;
+ }
+ private static void UpdateSettings()
+ {
+ melon = MelonCoroutines.Start(AttemptPlatformSwitch());
+ }
+
+ static IEnumerator AttemptPlatformSwitch()
+ {
+ if (MetaPort.Instance.isUsingVr)
+ {
+ //close the UI cause cohtml can get grumpy
+ ViewManager.Instance.UiStateToggle(false);
+ CVR_MenuManager.Instance.ToggleQuickMenu(false);
+ MelonLogger.Msg("Closed ChilloutVR UI.");
+
+ MetaPort.Instance.isUsingVr = false;
+ MelonLogger.Msg("Set MetaPort isUsingVr to false.");
+
+ SteamVR_Behaviour.instance.enabled = false;
+ SteamVR_Render.instance.enabled = false;
+
+ yield return new WaitForEndOfFrame();
+
+ PlayerSetup.Instance._inVr = false;
+ PlayerSetup.Instance.Invoke("CalibrateAvatar", 0f);
+ MelonLogger.Msg("Invoked CalibrateAvatar() on PlayerSetup.Instance.");
+ PlayerSetup.Instance.desktopCameraRig.SetActive(true);
+ PlayerSetup.Instance.vrCameraRig.SetActive(false);
+ CohtmlHud.Instance.gameObject.transform.parent = PlayerSetup.Instance.desktopCamera.transform;
+ MelonLogger.Msg("Enabled Desktop camera rig.");
+ MelonLogger.Msg("Set PlayerSetup _inVr to false.");
+
+ yield return new WaitForEndOfFrame();
+
+ MovementSystem.Instance.isVr = false;
+ MelonLogger.Msg("Set MovementSystem isVr to false.");
+ //CVR_MovementSystem.Instance.isVr = true;
+ //MelonLogger.Msg("Set CVR_MovementSystem isVR to false.");
+
+ yield return new WaitForSeconds(0.5f);
+
+ CVRInputManager.Instance.reload = true;
+ //CVRInputManager.Instance.inputEnabled = true;
+ //CVRInputManager.Instance.blockedByUi = false;
+ //CVRInputManager.Instance.independentHeadToggle = false;
+ //MelonLogger.Msg("Set CVRInputManager reload to true. Input should reload next frame...");
+
+ yield return new WaitForSeconds(1f);
+
+ CVRInputManager.Instance.reload = true;
+
+ yield return new WaitForSeconds(0.5f);
+
+ XRSettings.enabled = false;
+
+ PlayerSetup.Instance.Invoke("CalibrateAvatar", 0f);
+ MelonLogger.Msg("Invoked CalibrateAvatar() on PlayerSetup.Instance.");
+ //ViewManager.Instance.VrInputChanged(true);
+ }
+ else
+ {
+ //close the UI cause cohtml can get grumpy
+ ViewManager.Instance.UiStateToggle(false);
+ CVR_MenuManager.Instance.ToggleQuickMenu(false);
+ MelonLogger.Msg("Closed ChilloutVR UI.");
+
+ MelonCoroutines.Start(LoadDevice("OpenVR"));
+ MelonLogger.Msg("OpenVR device loaded!");
+
+ yield return new WaitForSeconds(3);
+
+ MelonLogger.Msg("Set MetaPort isUsingVr to true.");
+ MetaPort.Instance.isUsingVr = true;
+
+ yield return new WaitForEndOfFrame();
+
+ VRIK ik = (VRIK)PlayerSetup.Instance._avatar.GetComponent(typeof(VRIK));
+ if (ik == null)
+ {
+ ik = PlayerSetup.Instance._avatar.AddComponent();
+ }
+ ik.solver.IKPositionWeight = 0f;
+ ik.enabled = false;
+
+ PlayerSetup.Instance._inVr = true;
+ PlayerSetup.Instance.Invoke("CalibrateAvatar", 0f);
+ MelonLogger.Msg("Invoked CalibrateAvatar() on PlayerSetup.Instance.");
+ PlayerSetup.Instance.desktopCameraRig.SetActive(false);
+ PlayerSetup.Instance.vrCameraRig.SetActive(true);
+ CohtmlHud.Instance.gameObject.transform.parent = PlayerSetup.Instance.vrCamera.transform;
+ MelonLogger.Msg("Disabled Desktop camera rig.");
+ MelonLogger.Msg("Set PlayerSetup _inVr to true.");
+
+ yield return new WaitForEndOfFrame();
+
+ MovementSystem.Instance.isVr = true;
+ MelonLogger.Msg("Set MovementSystem isVr to false.");
+ //CVR_MovementSystem.Instance.isVr = true;
+ //MelonLogger.Msg("Set CVR_MovementSystem isVR to false.");
+
+ yield return new WaitForSeconds(0.5f);
+
+ CVRInputManager.Instance.reload = true;
+ //CVRInputManager.Instance.inputEnabled = true;
+ //CVRInputManager.Instance.blockedByUi = false;
+ //CVRInputManager.Instance.independentHeadToggle = false;
+ //MelonLogger.Msg("Set CVRInputManager reload to true. Input should reload next frame...");
+
+ yield return new WaitForSeconds(1f);
+
+ CVRInputManager.Instance.reload = true;
+
+ //PlayerSetup.Instance.Invoke("CalibrateAvatar", 0f);
+ //MelonLogger.Msg("Invoked CalibrateAvatar() on PlayerSetup.Instance.");
+
+ //ViewManager.Instance.VrInputChanged(true);
+ }
+
+ yield return null;
+ }
+
+ static IEnumerator LoadDevice(string newDevice)
+ {
+ if (String.Compare(XRSettings.loadedDeviceName, newDevice, true) != 0)
+ {
+ XRSettings.LoadDeviceByName(newDevice);
+ yield return null;
+ XRSettings.enabled = true;
+ if (SteamVR_Behaviour.instance.enabled == false)
+ {
+ SteamVR_Behaviour.instance.enabled = true;
+ SteamVR_Render.instance.enabled = true;
+ }
+ }
+ else
+ {
+ MelonLogger.Msg("OpenVR device already loaded!");
+ MelonCoroutines.Stop(melon);
+ yield return null;
+ XRSettings.enabled = true;
+ if (SteamVR_Behaviour.instance.enabled == false)
+ {
+ SteamVR_Behaviour.instance.enabled = true;
+ SteamVR_Render.instance.enabled = true;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/DesktopVRSwitch/Properties/AssemblyInfo.cs b/DesktopVRSwitch/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8ff8fcf
--- /dev/null
+++ b/DesktopVRSwitch/Properties/AssemblyInfo.cs
@@ -0,0 +1,30 @@
+using MelonLoader;
+using DesktopVRSwitch.Properties;
+using System.Reflection;
+
+
+[assembly: AssemblyVersion(AssemblyInfoParams.Version)]
+[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)]
+[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)]
+[assembly: AssemblyTitle(nameof(DesktopVRSwitch))]
+[assembly: AssemblyCompany(AssemblyInfoParams.Author)]
+[assembly: AssemblyProduct(nameof(DesktopVRSwitch))]
+
+[assembly: MelonInfo(
+ typeof(DesktopVRSwitch.DesktopVRSwitch),
+ nameof(DesktopVRSwitch),
+ AssemblyInfoParams.Version,
+ AssemblyInfoParams.Author,
+ downloadLink: "https://github.com/NotAKidOnSteam/DesktopVRSwitch"
+)]
+
+[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")]
+[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
+[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
+
+namespace DesktopVRSwitch.Properties;
+internal static class AssemblyInfoParams
+{
+ public const string Version = "1.0.0";
+ public const string Author = "NotAKidoS";
+}
\ No newline at end of file