diff --git a/CMakeLists.txt b/CMakeLists.txt
index 91d31197..0a92f8fe 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -254,7 +254,7 @@ add_subdirectory(${GEODE_BINDINGS_REPO_PATH} ${CMAKE_BINARY_DIR}/bindings)
 
 if (NOT GEODE_DISABLE_PRECOMPILED_HEADERS)
 	target_precompile_headers(GeodeBindings INTERFACE
-		"${GEODE_LOADER_PATH}/include/Geode/Bindings.hpp"
+		"$<$<COMPILE_LANGUAGE:CXX>:${GEODE_LOADER_PATH}/include/Geode/Bindings.hpp>"
 	)
 endif()
 
@@ -292,8 +292,8 @@ elseif (EXISTS ${GEODE_PLATFORM_BIN_PATH})
 	target_link_libraries(${PROJECT_NAME} INTERFACE "${GEODE_PLATFORM_BIN_PATH}")
 	if (NOT GEODE_DISABLE_PRECOMPILED_HEADERS)
 		target_precompile_headers(${PROJECT_NAME} INTERFACE
-			"${GEODE_LOADER_PATH}/include/Geode/DefaultInclude.hpp"
-			"${GEODE_LOADER_PATH}/include/Geode/Geode.hpp"
+			"$<$<COMPILE_LANGUAGE:CXX>:${GEODE_LOADER_PATH}/include/Geode/DefaultInclude.hpp>"
+			"$<$<COMPILE_LANGUAGE:CXX>:${GEODE_LOADER_PATH}/include/Geode/Geode.hpp>"
 			# please stop adding modify here its not here because it makes windows compilation take longer than geode 1.0 release date
 		)
 	endif()
diff --git a/loader/include/Geode/utils/cocos.hpp b/loader/include/Geode/utils/cocos.hpp
index 4192cdcb..a740f2ad 100644
--- a/loader/include/Geode/utils/cocos.hpp
+++ b/loader/include/Geode/utils/cocos.hpp
@@ -747,7 +747,7 @@ namespace geode::cocos {
      * @returns True if the node has the given sprite frame
      * name
      */
-    bool isSpriteFrameName(cocos2d::CCNode* node, const char* name);
+    GEODE_DLL bool isSpriteFrameName(cocos2d::CCNode* node, const char* name);
 
     /**
      * Get the first child that has the given sprite frame
@@ -759,7 +759,7 @@ namespace geode::cocos {
      * @returns Child with the given sprite frame name, or
      * nullptr if there is none
      */
-    cocos2d::CCNode* getChildBySpriteFrameName(cocos2d::CCNode* parent, const char* name);
+    GEODE_DLL cocos2d::CCNode* getChildBySpriteFrameName(cocos2d::CCNode* parent, const char* name);
 
     /**
      * Checks if a given file exists in CCFileUtils
diff --git a/loader/include/Geode/utils/general.hpp b/loader/include/Geode/utils/general.hpp
index 49354f6e..a151ae9d 100644
--- a/loader/include/Geode/utils/general.hpp
+++ b/loader/include/Geode/utils/general.hpp
@@ -117,7 +117,7 @@ namespace geode {
                 Num val;
                 char* strEnd;
                 errno = 0;
-                if (std::setlocale(LC_NUMERIC, "en_US.utf8")) {
+                if (std::setlocale(LC_NUMERIC, "C")) {
                     if constexpr (std::is_same_v<Num, float>) val = std::strtof(str.data(), &strEnd);
                     else if constexpr (std::is_same_v<Num, double>) val = std::strtod(str.data(), &strEnd);
                     else if constexpr (std::is_same_v<Num, long double>) val = std::strtold(str.data(), &strEnd);
diff --git a/loader/launcher/windows/Updater.cpp b/loader/launcher/windows/Updater.cpp
index 3a1506ef..8f26286a 100644
--- a/loader/launcher/windows/Updater.cpp
+++ b/loader/launcher/windows/Updater.cpp
@@ -22,33 +22,39 @@ bool waitForFile(std::filesystem::path const& path) {
         if (GetLastError() == ERROR_SHARING_VIOLATION) {
             Sleep(delay);
             // the delay would raise and go up to about 5 seconds, after which it will fail
-            if (delay < 5120)
+            if (delay < 5120) {
                 delay *= 2;
-        }
-        else
+            } else {
+                // delay too long, just give up now
+                hFile = NULL;
+                break;
+            }
+        } else {
             break;
+        }
     }
-    if (hFile)
+    if (hFile) {
         CloseHandle(hFile);
-    else {
+    } else {
         showError("Unable to update Geode: " + path.filename().string() + " is open by another process.");
         return false;
     }
     return true;
 }
 
-void updateFile(std::string const& name) {
+bool updateFile(std::string const& name) {
     std::error_code error;
     if (!std::filesystem::exists(updatesDir / name, error) || error)
-        return;
+        return true;
     if (!waitForFile(workingDir / name))
-        return;
+        return false;
 
     std::filesystem::rename(updatesDir / name, workingDir / name, error);
     if (error) {
         showError("Unable to update Geode: Unable to move " + name + " - " + error.message());
-        return;
+        return false;
     }
+    return true;
 }
 
 void removePath(std::filesystem::path const& path) {
@@ -98,10 +104,14 @@ int main(int argc, char* argv[]) {
         removePath(workingDir / "GeodeBootstrapper.dll");
 
     if (std::filesystem::exists(geodeDir) && std::filesystem::exists(updatesDir)) {
-        updateFile("XInput9_1_0.dll");
-        updateFile("Geode.dll");
+        bool updateSuccess = true;
+        updateSuccess &= updateFile("XInput9_1_0.dll");
+        updateSuccess &= updateFile("Geode.dll");
+        updateSuccess &= updateFile("Geode.pdb");
         updateResources();
-        removePath(updatesDir);
+        // if couldnt update the files, dont delete the updates folder
+        if (updateSuccess)
+            removePath(updatesDir);
     }
 
     if (argc < 2)
diff --git a/loader/src/hooks/ImpostorPlayLayerFix.cpp b/loader/src/hooks/ImpostorPlayLayerFix.cpp
new file mode 100644
index 00000000..2f17f97b
--- /dev/null
+++ b/loader/src/hooks/ImpostorPlayLayerFix.cpp
@@ -0,0 +1,18 @@
+#include <Geode/DefaultInclude.hpp>
+#include <Geode/modify/LevelPage.hpp>
+
+using namespace geode::prelude;
+
+// When pressing spacebar during the transition into LevelSelectLayer,
+// a PlayLayer will be created but it will never be added to a scene.
+// It will still exist in memory, potentially causing issues in mods, i.e. Custom Keybinds.
+//
+// This workaround solves the issue by making it impossible to start the level during a transition.
+
+struct CustomLevelPage : Modify<CustomLevelPage, LevelPage> {
+    void onPlay(cocos2d::CCObject* sender) {
+        if (!typeinfo_cast<CCTransitionScene*>(CCScene::get())) {
+            LevelPage::onPlay(sender);
+        }
+    }
+};
diff --git a/loader/src/platform/windows/console.cpp b/loader/src/platform/windows/console.cpp
index 540e77a1..028f2cfa 100644
--- a/loader/src/platform/windows/console.cpp
+++ b/loader/src/platform/windows/console.cpp
@@ -117,7 +117,7 @@ void console::setup() {
 
             // count == 0 => not a console and not a file, assume it's closed
             // wine does something weird with /dev/null? not sure tbh but it's definitely up to no good
-            if (count == 0 || path.ends_with("\\dev\\null")) {
+            if ((count == 0 || path.ends_with("\\dev\\null")) && Mod::get()->getSettingValue<bool>("show-platform-console")) {
                 s_outHandle = nullptr;
                 CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE));
                 CloseHandle(GetStdHandle(STD_INPUT_HANDLE));
diff --git a/loader/src/utils/cocos.cpp b/loader/src/utils/cocos.cpp
index 58caf709..cd53788b 100644
--- a/loader/src/utils/cocos.cpp
+++ b/loader/src/utils/cocos.cpp
@@ -340,6 +340,8 @@ std::shared_ptr<WeakRefController> WeakRefPool::manage(CCObject* obj) {
 }
 
 bool geode::cocos::isSpriteFrameName(CCNode* node, const char* name) {
+    if (!node) return false;
+
     auto cache = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(name);
     if (!cache) return false;