From 4028cdd6693faa93bf8558f3e2440e4d35736ba7 Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Fri, 23 Jan 2026 01:23:04 +0100 Subject: [PATCH 1/9] init --- src/WeatherEditor/Weather/WeatherWidget.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/WeatherEditor/Weather/WeatherWidget.cpp b/src/WeatherEditor/Weather/WeatherWidget.cpp index 9350a88169..aa17bf6e58 100644 --- a/src/WeatherEditor/Weather/WeatherWidget.cpp +++ b/src/WeatherEditor/Weather/WeatherWidget.cpp @@ -1488,6 +1488,9 @@ void WeatherWidget::LoadFeatureSettings() json featureJson; if (weatherManager->LoadSettingsFromWeather(weather, featureName, featureJson)) { + // LoadSettingsFromWeather returns true only when __enabled is true in the cache + // Add it to the settings for the UI to display correctly + featureJson["__enabled"] = true; settings.featureSettings[featureName] = featureJson; } } From c4cfe257bcd74c616ae1ef6e8c62edbfa5efe556 Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Fri, 23 Jan 2026 17:10:24 +0100 Subject: [PATCH 2/9] add debug logging --- src/WeatherManager.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/WeatherManager.cpp b/src/WeatherManager.cpp index 41f3ec39b1..dc4f79de1c 100644 --- a/src/WeatherManager.cpp +++ b/src/WeatherManager.cpp @@ -73,6 +73,12 @@ void WeatherManager::UpdateFeatures() // Always update if lerp factor changes or weather changed if (weatherChanged || std::abs(currentWeathers.lerpFactor - lastKnownWeather.lerpFactor) > 0.001f) { + if (weatherChanged) { + logger::info("Weather changed - Current: {}, Last: {}", + currentWeathers.currentWeather ? GetWeatherKey(currentWeathers.currentWeather) : "None", + currentWeathers.lastWeather ? GetWeatherKey(currentWeathers.lastWeather) : "None"); + } + auto* globalRegistry = WeatherVariables::GlobalWeatherRegistry::GetSingleton(); // Get all features and update those that have registered weather variables @@ -90,12 +96,18 @@ void WeatherManager::UpdateFeatures() // Load settings for last weather (from) if (currentWeathers.lastWeather && currentWeathers.lerpFactor < 1.0f) { - LoadSettingsFromWeather(currentWeathers.lastWeather, featureName, currWeatherSettings); + bool loadedLast = LoadSettingsFromWeather(currentWeathers.lastWeather, featureName, currWeatherSettings); + if (loadedLast) { + logger::info("Loaded {} settings for last weather: {}", featureName, GetWeatherKey(currentWeathers.lastWeather)); + } } // Load settings for current weather (to) if (currentWeathers.currentWeather) { - LoadSettingsFromWeather(currentWeathers.currentWeather, featureName, nextWeatherSettings); + bool loadedCurrent = LoadSettingsFromWeather(currentWeathers.currentWeather, featureName, nextWeatherSettings); + if (loadedCurrent) { + logger::info("Loaded {} settings for current weather: {}", featureName, GetWeatherKey(currentWeathers.currentWeather)); + } } // Let the global registry handle variable interpolation From 7a6b9a29caa818d6c0cf9fa4b6b230a1bc36c7b3 Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Fri, 23 Jan 2026 17:40:13 +0100 Subject: [PATCH 3/9] different debugs --- src/WeatherManager.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/WeatherManager.cpp b/src/WeatherManager.cpp index dc4f79de1c..4f672c58fd 100644 --- a/src/WeatherManager.cpp +++ b/src/WeatherManager.cpp @@ -52,6 +52,11 @@ void WeatherManager::LoadPerWeatherSettingsFromDisk() if (weatherData.is_object()) { for (auto& [featureName, featureSettings] : weatherData.items()) { perWeatherSettingsCache[weatherKey][featureName] = featureSettings; + // Log if __enabled flag is present and its value + bool hasEnabled = featureSettings.contains("__enabled"); + bool enabledValue = featureSettings.value("__enabled", false); + logger::info("Loaded {} for weather {} - __enabled present: {}, value: {}", + featureName, weatherKey, hasEnabled, enabledValue); } logger::info("Loaded settings for weather: {}", weatherKey); } @@ -73,12 +78,6 @@ void WeatherManager::UpdateFeatures() // Always update if lerp factor changes or weather changed if (weatherChanged || std::abs(currentWeathers.lerpFactor - lastKnownWeather.lerpFactor) > 0.001f) { - if (weatherChanged) { - logger::info("Weather changed - Current: {}, Last: {}", - currentWeathers.currentWeather ? GetWeatherKey(currentWeathers.currentWeather) : "None", - currentWeathers.lastWeather ? GetWeatherKey(currentWeathers.lastWeather) : "None"); - } - auto* globalRegistry = WeatherVariables::GlobalWeatherRegistry::GetSingleton(); // Get all features and update those that have registered weather variables @@ -95,19 +94,19 @@ void WeatherManager::UpdateFeatures() json nextWeatherSettings; // Load settings for last weather (from) - if (currentWeathers.lastWeather && currentWeathers.lerpFactor < 1.0f) { - bool loadedLast = LoadSettingsFromWeather(currentWeathers.lastWeather, featureName, currWeatherSettings); - if (loadedLast) { - logger::info("Loaded {} settings for last weather: {}", featureName, GetWeatherKey(currentWeathers.lastWeather)); - } + // Use game's lastWeather if available, otherwise fall back to our tracked lastKnownWeather + RE::TESWeather* fromWeather = currentWeathers.lastWeather; + if (!fromWeather && lastKnownWeather.currentWeather) { + fromWeather = lastKnownWeather.currentWeather; + } + + if (fromWeather && currentWeathers.lerpFactor < 1.0f) { + LoadSettingsFromWeather(fromWeather, featureName, currWeatherSettings); } // Load settings for current weather (to) if (currentWeathers.currentWeather) { - bool loadedCurrent = LoadSettingsFromWeather(currentWeathers.currentWeather, featureName, nextWeatherSettings); - if (loadedCurrent) { - logger::info("Loaded {} settings for current weather: {}", featureName, GetWeatherKey(currentWeathers.currentWeather)); - } + LoadSettingsFromWeather(currentWeathers.currentWeather, featureName, nextWeatherSettings); } // Let the global registry handle variable interpolation From fce13a8fd3371ec98328e9ca584cb26b99c90d25 Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Fri, 23 Jan 2026 17:48:32 +0100 Subject: [PATCH 4/9] ctd fix --- src/WeatherManager.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/WeatherManager.cpp b/src/WeatherManager.cpp index 4f672c58fd..804aeb3e2e 100644 --- a/src/WeatherManager.cpp +++ b/src/WeatherManager.cpp @@ -53,15 +53,19 @@ void WeatherManager::LoadPerWeatherSettingsFromDisk() for (auto& [featureName, featureSettings] : weatherData.items()) { perWeatherSettingsCache[weatherKey][featureName] = featureSettings; // Log if __enabled flag is present and its value - bool hasEnabled = featureSettings.contains("__enabled"); - bool enabledValue = featureSettings.value("__enabled", false); - logger::info("Loaded {} for weather {} - __enabled present: {}, value: {}", - featureName, weatherKey, hasEnabled, enabledValue); + if (featureSettings.is_object()) { + bool hasEnabled = featureSettings.contains("__enabled"); + bool enabledValue = featureSettings.value("__enabled", false); + logger::info("Loaded {} for weather {} - __enabled present: {}, value: {}", + featureName, weatherKey, hasEnabled, enabledValue); + } else { + logger::warn("Feature {} for weather {} is not a valid JSON object", featureName, weatherKey); + } } logger::info("Loaded settings for weather: {}", weatherKey); } - } catch (const nlohmann::json::parse_error& e) { - logger::warn("Error parsing weather settings file ({}): {}", entry.path().string(), e.what()); + } catch (const std::exception& e) { + logger::warn("Error loading weather settings file ({}): {}", entry.path().string(), e.what()); } } From 76d79b2619571a9b77e2df5227b64bbc185f8899 Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Fri, 23 Jan 2026 19:33:51 +0100 Subject: [PATCH 5/9] rollback --- src/WeatherManager.cpp | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/src/WeatherManager.cpp b/src/WeatherManager.cpp index 804aeb3e2e..41f3ec39b1 100644 --- a/src/WeatherManager.cpp +++ b/src/WeatherManager.cpp @@ -52,20 +52,11 @@ void WeatherManager::LoadPerWeatherSettingsFromDisk() if (weatherData.is_object()) { for (auto& [featureName, featureSettings] : weatherData.items()) { perWeatherSettingsCache[weatherKey][featureName] = featureSettings; - // Log if __enabled flag is present and its value - if (featureSettings.is_object()) { - bool hasEnabled = featureSettings.contains("__enabled"); - bool enabledValue = featureSettings.value("__enabled", false); - logger::info("Loaded {} for weather {} - __enabled present: {}, value: {}", - featureName, weatherKey, hasEnabled, enabledValue); - } else { - logger::warn("Feature {} for weather {} is not a valid JSON object", featureName, weatherKey); - } } logger::info("Loaded settings for weather: {}", weatherKey); } - } catch (const std::exception& e) { - logger::warn("Error loading weather settings file ({}): {}", entry.path().string(), e.what()); + } catch (const nlohmann::json::parse_error& e) { + logger::warn("Error parsing weather settings file ({}): {}", entry.path().string(), e.what()); } } @@ -98,14 +89,8 @@ void WeatherManager::UpdateFeatures() json nextWeatherSettings; // Load settings for last weather (from) - // Use game's lastWeather if available, otherwise fall back to our tracked lastKnownWeather - RE::TESWeather* fromWeather = currentWeathers.lastWeather; - if (!fromWeather && lastKnownWeather.currentWeather) { - fromWeather = lastKnownWeather.currentWeather; - } - - if (fromWeather && currentWeathers.lerpFactor < 1.0f) { - LoadSettingsFromWeather(fromWeather, featureName, currWeatherSettings); + if (currentWeathers.lastWeather && currentWeathers.lerpFactor < 1.0f) { + LoadSettingsFromWeather(currentWeathers.lastWeather, featureName, currWeatherSettings); } // Load settings for current weather (to) From 75a621ec4dac1152b8fc50a9bdded616add953ce Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Fri, 23 Jan 2026 19:48:25 +0100 Subject: [PATCH 6/9] enforce saving/loading consistency --- src/WeatherEditor/Weather/WeatherWidget.cpp | 3 --- src/WeatherManager.cpp | 25 +++++++++++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/WeatherEditor/Weather/WeatherWidget.cpp b/src/WeatherEditor/Weather/WeatherWidget.cpp index aa17bf6e58..9350a88169 100644 --- a/src/WeatherEditor/Weather/WeatherWidget.cpp +++ b/src/WeatherEditor/Weather/WeatherWidget.cpp @@ -1488,9 +1488,6 @@ void WeatherWidget::LoadFeatureSettings() json featureJson; if (weatherManager->LoadSettingsFromWeather(weather, featureName, featureJson)) { - // LoadSettingsFromWeather returns true only when __enabled is true in the cache - // Add it to the settings for the UI to display correctly - featureJson["__enabled"] = true; settings.featureSettings[featureName] = featureJson; } } diff --git a/src/WeatherManager.cpp b/src/WeatherManager.cpp index 41f3ec39b1..a7e5d6ed23 100644 --- a/src/WeatherManager.cpp +++ b/src/WeatherManager.cpp @@ -48,12 +48,18 @@ void WeatherManager::LoadPerWeatherSettingsFromDisk() settingsFile.close(); // Store the entire weather settings in cache - // The structure is expected to be: { "FeatureName": { settings }, ... } - if (weatherData.is_object()) { - for (auto& [featureName, featureSettings] : weatherData.items()) { + // The structure is expected to be: { "featureSettings": { "FeatureName": { settings }, ... } + if (weatherData.is_object() && weatherData.contains("featureSettings") && weatherData["featureSettings"].is_object()) { + for (auto& [featureName, featureSettings] : weatherData["featureSettings"].items()) { perWeatherSettingsCache[weatherKey][featureName] = featureSettings; } logger::info("Loaded settings for weather: {}", weatherKey); + } else if (weatherData.is_object()) { + // Legacy format support: { "FeatureName": { settings }, ... } + for (auto& [featureName, featureSettings] : weatherData.items()) { + perWeatherSettingsCache[weatherKey][featureName] = featureSettings; + } + logger::info("Loading weather {} with legacy flat format, will convert on save", weatherKey); } } catch (const nlohmann::json::parse_error& e) { logger::warn("Error parsing weather settings file ({}): {}", entry.path().string(), e.what()); @@ -157,18 +163,23 @@ void WeatherManager::SaveSettingsToWeather(RE::TESWeather* weather, const std::s } } + // Ensure weatherData has featureSettings object + if (!weatherData.contains("featureSettings") || !weatherData["featureSettings"].is_object()) { + weatherData["featureSettings"] = json::object(); + } + // Update with new feature settings or remove feature entry if settings empty if (settings.is_object() && settings.empty()) { // Remove feature entry from loaded JSON - if (weatherData.is_object()) { - weatherData.erase(featureName); + if (weatherData["featureSettings"].is_object()) { + weatherData["featureSettings"].erase(featureName); } } else { - weatherData[featureName] = settings; + weatherData["featureSettings"][featureName] = settings; } // Write back to disk - if (weatherData.is_object() && weatherData.empty()) { + if (weatherData["featureSettings"].is_object() && weatherData["featureSettings"].empty()) { // No features left for this weather — remove file if it exists if (std::filesystem::exists(filePath)) { try { From ac152175306329aa92a29990eefaac474681a7e1 Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Sat, 24 Jan 2026 00:35:55 +0100 Subject: [PATCH 7/9] remove legacy support --- src/WeatherManager.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/WeatherManager.cpp b/src/WeatherManager.cpp index a7e5d6ed23..84d58e014d 100644 --- a/src/WeatherManager.cpp +++ b/src/WeatherManager.cpp @@ -54,12 +54,6 @@ void WeatherManager::LoadPerWeatherSettingsFromDisk() perWeatherSettingsCache[weatherKey][featureName] = featureSettings; } logger::info("Loaded settings for weather: {}", weatherKey); - } else if (weatherData.is_object()) { - // Legacy format support: { "FeatureName": { settings }, ... } - for (auto& [featureName, featureSettings] : weatherData.items()) { - perWeatherSettingsCache[weatherKey][featureName] = featureSettings; - } - logger::info("Loading weather {} with legacy flat format, will convert on save", weatherKey); } } catch (const nlohmann::json::parse_error& e) { logger::warn("Error parsing weather settings file ({}): {}", entry.path().string(), e.what()); From c6fb1f909f3b7d18cb2e2ed2135982b37fc32f9b Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Sat, 24 Jan 2026 13:54:43 +0100 Subject: [PATCH 8/9] cleanup and adressign AI comments. --- src/WeatherManager.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/WeatherManager.cpp b/src/WeatherManager.cpp index 84d58e014d..8975e058bb 100644 --- a/src/WeatherManager.cpp +++ b/src/WeatherManager.cpp @@ -157,23 +157,25 @@ void WeatherManager::SaveSettingsToWeather(RE::TESWeather* weather, const std::s } } - // Ensure weatherData has featureSettings object + // Ensure weatherData is an object and has featureSettings + if (!weatherData.is_object()) { + weatherData = json::object(); + } if (!weatherData.contains("featureSettings") || !weatherData["featureSettings"].is_object()) { weatherData["featureSettings"] = json::object(); } + auto& featureSettings = weatherData["featureSettings"]; // Update with new feature settings or remove feature entry if settings empty if (settings.is_object() && settings.empty()) { // Remove feature entry from loaded JSON - if (weatherData["featureSettings"].is_object()) { - weatherData["featureSettings"].erase(featureName); - } + featureSettings.erase(featureName); } else { - weatherData["featureSettings"][featureName] = settings; + featureSettings[featureName] = settings; } // Write back to disk - if (weatherData["featureSettings"].is_object() && weatherData["featureSettings"].empty()) { + if (featureSettings.empty()) { // No features left for this weather — remove file if it exists if (std::filesystem::exists(filePath)) { try { From b78715d1ad4ac11c13cb87c092dbd51c2688b0b3 Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Sat, 24 Jan 2026 17:04:17 +0100 Subject: [PATCH 9/9] apply nitpick --- src/WeatherManager.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/WeatherManager.cpp b/src/WeatherManager.cpp index 8975e058bb..abb8ad1c56 100644 --- a/src/WeatherManager.cpp +++ b/src/WeatherManager.cpp @@ -177,13 +177,11 @@ void WeatherManager::SaveSettingsToWeather(RE::TESWeather* weather, const std::s // Write back to disk if (featureSettings.empty()) { // No features left for this weather — remove file if it exists - if (std::filesystem::exists(filePath)) { - try { - std::filesystem::remove(filePath); - logger::info("Removed weather settings file (no features remain): {}", filePath); - } catch (const std::filesystem::filesystem_error& e) { - logger::warn("Failed to remove empty weather settings file ({}): {}", filePath, e.what()); - } + std::error_code ec; + if (std::filesystem::remove(filePath, ec)) { + logger::info("Removed weather settings file (no features remain): {}", filePath); + } else if (ec) { + logger::warn("Failed to remove empty weather settings file ({}): {}", filePath, ec.message()); } return; }