From 7e8f99ead47b5645b3f08b58efddafaee575aa88 Mon Sep 17 00:00:00 2001 From: Chomp Date: Mon, 29 Sep 2025 15:53:05 +0100 Subject: [PATCH 1/9] First pass at Weather generation refactor --- .../SPT_Data/configs/weather.json | 217 +++++++++++++++--- .../Controllers/WeatherController.cs | 13 +- .../Generators/WeatherGenerator.cs | 179 ++++++++++++--- .../Models/Eft/Weather/WeatherData.cs | 4 + .../Models/Spt/Config/WeatherConfig.cs | 18 +- .../Services/RaidWeatherService.cs | 10 +- 6 files changed, 372 insertions(+), 69 deletions(-) diff --git a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json index 559540700..eaafa3962 100644 --- a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json +++ b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json @@ -2,30 +2,102 @@ "acceleration": 7, "weather": { "generateWeatherAmountHours": 24, - "seasonValues": { - "default": { + "presetWeights": { + "SUNNY": { "clouds": { + "-1": 5, + "-0.8": 2 + }, + "windSpeed": { "values": [ - -1, - -0.8, - -0.5, - 0.1, 0, - 0.15, - 0.4, - 1 + 1, + 2, + 3, + 4 ], "weights": [ - 70, - 22, - 22, - 15, - 15, - 15, + 6, + 3, + 2, + 1, + 1 + ] + }, + "windDirection": { + "values": [ + 1, + 2, + 3, + 4, 5, - 4 + 6, + 7, + 8 + ], + "weights": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 ] }, + "windGustiness": { + "min": 0, + "max": 1 + }, + "rain": { + "values": [ + 1 + ], + "weights": [ + 1 + ] + }, + "rainIntensity": { + "min": 0, + "max": 0 + }, + "fog": { + "values": [ + 0.0013, + 0.0018, + 0.002, + 0.004, + 0.006 + ], + "weights": [ + 35, + 6, + 4, + 3, + 1 + ] + }, + "temp": { + "day": { + "min": 9, + "max": 32 + }, + "night": { + "min": 2, + "max": 16 + } + }, + "pressure": { + "min": 760, + "max": 780 + } + }, + "RAINY": { + "clouds": { + "0.4": 5, + "1": 4 + }, "windSpeed": { "values": [ 0, @@ -70,22 +142,20 @@ }, "rain": { "values": [ - 1, 2, 3, 4, 5 ], "weights": [ - 20, - 1, - 1, - 1, - 1 + 5, + 5, + 5, + 5 ] }, "rainIntensity": { - "min": 0, + "min": 0.1, "max": 1 }, "fog": { @@ -119,19 +189,105 @@ "max": 780 } }, - "WINTER": { + "CLOUDY": { "clouds": { + "0.1": 10, + "0": 10, + "0.15": 10, + "0.4": 10, + "1": 10 + }, + "windSpeed": { "values": [ - -1, - 0.65, - 1 + 0, + 1, + 2, + 3, + 4 ], "weights": [ + 6, + 3, + 2, + 1, + 1 + ] + }, + "windDirection": { + "values": [ + 1, 2, + 3, + 4, + 5, + 6, + 7, + 8 + ], + "weights": [ + 1, + 1, + 1, 1, + 1, + 1, + 1, + 1 + ] + }, + "windGustiness": { + "min": 0, + "max": 1 + }, + "rain": { + "values": [ + 1 + ], + "weights": [ + 1 + ] + }, + "rainIntensity": { + "min": 0, + "max": 1 + }, + "fog": { + "values": [ + 0.0013, + 0.0018, + 0.002, + 0.004, + 0.006 + ], + "weights": [ + 35, + 6, + 4, + 3, 1 ] }, + "temp": { + "day": { + "min": 9, + "max": 32 + }, + "night": { + "min": 2, + "max": 16 + } + }, + "pressure": { + "min": 760, + "max": 780 + } + }, + "WINTER": { + "clouds": { + "-1": 2, + "0.65": 1, + "1": 1 + }, "windSpeed": { "values": [ 0, @@ -235,7 +391,12 @@ 1, 2 ] - } + }, + "weatherPresetWeight": { + "SUNNY": 8, + "RAINY": 8, + "CLOUDY": 8 + } }, "seasonDates": [ { diff --git a/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs b/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs index 3ba8d0c1f..f98483be0 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs @@ -3,8 +3,11 @@ using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Weather; using SPTarkov.Server.Core.Models.Enums; +using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Spt.Weather; +using SPTarkov.Server.Core.Servers; using SPTarkov.Server.Core.Services; +using SPTarkov.Server.Core.Utils.Cloners; namespace SPTarkov.Server.Core.Controllers; @@ -12,9 +15,13 @@ namespace SPTarkov.Server.Core.Controllers; public class WeatherController( WeatherGenerator weatherGenerator, SeasonalEventService seasonalEventService, - RaidWeatherService raidWeatherService + RaidWeatherService raidWeatherService, + ConfigServer configServer, + ICloner cloner ) { + protected readonly WeatherConfig WeatherConfig = configServer.GetConfig(); + /// /// Handle client/weather /// @@ -31,7 +38,9 @@ public WeatherData Generate() }; weatherGenerator.CalculateGameTime(result); - result.Weather = weatherGenerator.GenerateWeather(result.Season.Value); + + var presetWeights = cloner.Clone(WeatherConfig.Weather.WeatherPresetWeight); + result.Weather = weatherGenerator.GenerateWeather(result.Season.Value, ref presetWeights); return result; } diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs index 3f7c033f8..c3f1b282a 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs @@ -4,20 +4,24 @@ using SPTarkov.Server.Core.Models.Eft.Weather; using SPTarkov.Server.Core.Models.Enums; using SPTarkov.Server.Core.Models.Spt.Config; +using SPTarkov.Server.Core.Models.Utils; using SPTarkov.Server.Core.Servers; using SPTarkov.Server.Core.Services; using SPTarkov.Server.Core.Utils; +using SPTarkov.Server.Core.Utils.Cloners; namespace SPTarkov.Server.Core.Generators; [Injectable] public class WeatherGenerator( + ISptLogger logger, TimeUtil timeUtil, SeasonalEventService seasonalEventService, WeatherHelper weatherHelper, ConfigServer configServer, WeightedRandomHelper weightedRandomHelper, - RandomUtil randomUtil + RandomUtil randomUtil, + ICloner cloner ) { protected readonly WeatherConfig WeatherConfig = configServer.GetConfig(); @@ -50,52 +54,161 @@ protected string GetBsgFormattedInRaidTime() } /// - /// Return randomised Weather data with help of config/weather.json + /// Generate a weather object to send to client /// - /// The currently active season - /// Optional, what timestamp to generate the weather data at, defaults to now when not supplied - /// Randomised weather data - public Weather GenerateWeather(Season currentSeason, long? timestamp = null) + /// Whaat season is weather being generated for + /// Weather preset weights to pick from + /// Optional - Current time + /// Optional -What weather preset was last generated + /// Weather + public Weather GenerateWeather( + Season currentSeason, + ref Dictionary presetWeights, + long? timestamp = null, + WeatherPreset? previousPreset = null + ) { - var weatherValues = GetWeatherValuesBySeason(currentSeason); - var clouds = GetWeightedClouds(weatherValues); + if (previousPreset is not null && presetWeights.Any()) + { + // We know last picked preset, Adjust weights + // Make it less likely to be picked now + presetWeights[previousPreset.Value] -= 1; + logger.Info($"{previousPreset.Value} weight reduced by: 1 to: {presetWeights[previousPreset.Value]}"); + } + else + { + // Get fresh cloned weights from config + presetWeights = cloner.Clone(WeatherConfig.Weather.WeatherPresetWeight); + } + + // Assign value to previousPreset to be picked up next loop + previousPreset = weightedRandomHelper.GetWeightedValue(presetWeights); + logger.Warning($"Chose: {previousPreset}"); + + // Check if chosen preset has been exhausted and reset if necessary + if (presetWeights[previousPreset.Value] <= 0) + { + logger.Info($"{previousPreset.Value} is 0, resetting weights"); + // Force fresh presets to be picked + presetWeights.Clear(); + } + + return GenerateWeatherByPreset(previousPreset.Value, currentSeason, timestamp); + } + + protected Weather GenerateWeatherByPreset(WeatherPreset chosenPreset, Season currentSeason, long? timestamp) + { + // TODO: handle currentSeason, apply additive values/overwrite existing? + + Weather result; + var presetWeights = GetWeatherWeightsByPreset(chosenPreset); + switch (chosenPreset) + { + case WeatherPreset.SUNNY: + result = GenerateSunnyWeather(presetWeights); + break; + case WeatherPreset.RAINY: + result = GenerateRainyWeather(presetWeights); + break; + case WeatherPreset.CLOUDY: + result = GenerateCloudyWeather(presetWeights); + break; + default: + presetWeights = GetWeatherWeightsByPreset(WeatherPreset.SUNNY); + result = GenerateSunnyWeather(presetWeights); + break; + } + + // Set time values in result using now or passed in timestamp + SetCurrentDateTime(result, timestamp); + + // Must occur after SetCurrentDateTime() + result.Temperature = GetRaidTemperature(presetWeights, result.SptInRaidTimestamp ?? 0); + + // Needed by RaidWeatherService + result.SptChosenPreset = chosenPreset; + + return result; + } + + protected Weather GenerateSunnyWeather(PresetWeights weatherWeights) + { + var result = new Weather + { + Pressure = GetRandomDouble(weatherWeights.Pressure.Min, weatherWeights.Pressure.Max), + Temperature = 0, // Handled in caller + Fog = GetWeightedFog(weatherWeights), + RainIntensity = 0, + Rain = 0, + WindGustiness = GetRandomDouble(weatherWeights.WindGustiness.Min, weatherWeights.WindGustiness.Max, 2), + WindDirection = GetWeightedWindDirection(weatherWeights), + WindSpeed = GetWeightedWindSpeed(weatherWeights), + Cloud = GetWeightedClouds(weatherWeights), + Time = string.Empty, + Date = string.Empty, + Timestamp = 0, + SptInRaidTimestamp = 0, // Handled in caller + }; + + return result; + } - // Force rain to off if no clouds - var rain = clouds <= 0.6 ? 0 : GetWeightedRain(weatherValues); + protected Weather GenerateRainyWeather(PresetWeights weatherWeights) + { + var clouds = GetWeightedClouds(weatherWeights); - // TODO: Ensure Weather settings match Ts Server GetRandomDouble produces a decimal value way higher than ts server var result = new Weather { - Pressure = GetRandomDouble(weatherValues.Pressure.Min, weatherValues.Pressure.Max), - Temperature = 0, - Fog = GetWeightedFog(weatherValues), - RainIntensity = rain > 1 ? GetRandomDouble(weatherValues.RainIntensity.Min, weatherValues.RainIntensity.Max) : 0, - Rain = rain, - WindGustiness = GetRandomDouble(weatherValues.WindGustiness.Min, weatherValues.WindGustiness.Max, 2), - WindDirection = GetWeightedWindDirection(weatherValues), - WindSpeed = GetWeightedWindSpeed(weatherValues), + Pressure = GetRandomDouble(weatherWeights.Pressure.Min, weatherWeights.Pressure.Max), + Temperature = 0, // // Handled in caller + Fog = GetWeightedFog(weatherWeights), + RainIntensity = GetRandomDouble(weatherWeights.RainIntensity.Min, weatherWeights.RainIntensity.Max), + Rain = GetWeightedRain(weatherWeights), + WindGustiness = GetRandomDouble(weatherWeights.WindGustiness.Min, weatherWeights.WindGustiness.Max, 2), + WindDirection = GetWeightedWindDirection(weatherWeights), + WindSpeed = GetWeightedWindSpeed(weatherWeights), Cloud = clouds, Time = string.Empty, Date = string.Empty, Timestamp = 0, - SptInRaidTimestamp = 0, + SptInRaidTimestamp = 0, // Handled in caller }; - SetCurrentDateTime(result, timestamp); + return result; + } + + protected Weather GenerateCloudyWeather(PresetWeights weatherWeights) + { + var clouds = GetWeightedClouds(weatherWeights); - result.Temperature = GetRaidTemperature(weatherValues, result.SptInRaidTimestamp ?? 0); + var result = new Weather + { + Pressure = GetRandomDouble(weatherWeights.Pressure.Min, weatherWeights.Pressure.Max), + Temperature = 0, // Handled in caller + Fog = GetWeightedFog(weatherWeights), + RainIntensity = 0, + Rain = 0, + WindGustiness = GetRandomDouble(weatherWeights.WindGustiness.Min, weatherWeights.WindGustiness.Max, 2), + WindDirection = GetWeightedWindDirection(weatherWeights), + WindSpeed = GetWeightedWindSpeed(weatherWeights), + Cloud = clouds, + Time = string.Empty, + Date = string.Empty, + Timestamp = 0, + SptInRaidTimestamp = 0, // Handled in caller + }; return result; } - protected SeasonalValues GetWeatherValuesBySeason(Season currentSeason) + protected PresetWeights GetWeatherWeightsByPreset(WeatherPreset weatherPreset) { - if (!WeatherConfig.Weather.SeasonValues.TryGetValue(currentSeason.ToString(), out var value)) + if (!WeatherConfig.Weather.PresetWeights.TryGetValue(weatherPreset.ToString(), out var value)) { - return WeatherConfig.Weather.SeasonValues["default"]; + return WeatherConfig.Weather.PresetWeights["default"]; } - return value!; + return value; } /// @@ -104,7 +217,7 @@ protected SeasonalValues GetWeatherValuesBySeason(Season currentSeason) /// What season Tarkov is currently in /// What time is the raid running at /// Timestamp - protected double GetRaidTemperature(SeasonalValues weather, long inRaidTimestamp) + protected double GetRaidTemperature(PresetWeights weather, long inRaidTimestamp) { // Convert timestamp to date so we can get current hour and check if its day or night var currentRaidTime = new DateTime(inRaidTimestamp); @@ -131,27 +244,27 @@ protected void SetCurrentDateTime(Weather weather, long? timestamp = null) weather.SptInRaidTimestamp = weather.Timestamp; } - protected WindDirection GetWeightedWindDirection(SeasonalValues weather) + protected WindDirection GetWeightedWindDirection(PresetWeights weather) { return weightedRandomHelper.WeightedRandom(weather.WindDirection.Values, weather.WindDirection.Weights).Item; } - protected double GetWeightedClouds(SeasonalValues weather) + protected double GetWeightedClouds(PresetWeights weather) { - return weightedRandomHelper.WeightedRandom(weather.Clouds.Values, weather.Clouds.Weights).Item; + return double.Parse(weightedRandomHelper.GetWeightedValue(weather.Clouds)); } - protected double GetWeightedWindSpeed(SeasonalValues weather) + protected double GetWeightedWindSpeed(PresetWeights weather) { return weightedRandomHelper.WeightedRandom(weather.WindSpeed.Values, weather.WindSpeed.Weights).Item; } - protected double GetWeightedFog(SeasonalValues weather) + protected double GetWeightedFog(PresetWeights weather) { return weightedRandomHelper.WeightedRandom(weather.Fog.Values, weather.Fog.Weights).Item; } - protected double GetWeightedRain(SeasonalValues weather) + protected double GetWeightedRain(PresetWeights weather) { return weightedRandomHelper.WeightedRandom(weather.Rain.Values, weather.Rain.Weights).Item; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Eft/Weather/WeatherData.cs b/Libraries/SPTarkov.Server.Core/Models/Eft/Weather/WeatherData.cs index 83d4addb9..398d57fc1 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Eft/Weather/WeatherData.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Eft/Weather/WeatherData.cs @@ -1,5 +1,6 @@ using System.Text.Json.Serialization; using SPTarkov.Server.Core.Models.Enums; +using SPTarkov.Server.Core.Models.Spt.Config; namespace SPTarkov.Server.Core.Models.Eft.Weather; @@ -67,4 +68,7 @@ public record Weather [JsonPropertyName("sptInRaidTimestamp")] public long? SptInRaidTimestamp { get; set; } + + [JsonPropertyName("sptChosenPreset")] + public WeatherPreset? SptChosenPreset { get; set; } } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs index 456702c3b..03681038c 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs @@ -50,8 +50,8 @@ public record SeasonDateTimes public record WeatherValues { - [JsonPropertyName("seasonValues")] - public Dictionary? SeasonValues { get; set; } + [JsonPropertyName("presetWeights")] + public Dictionary? PresetWeights { get; set; } /// /// How many hours to generate weather data into the future @@ -64,12 +64,22 @@ public record WeatherValues /// [JsonPropertyName("timePeriod")] public WeatherSettings? TimePeriod { get; set; } + + [JsonPropertyName("weatherPresetWeight")] + public Dictionary WeatherPresetWeight { get; set; } +} + +public enum WeatherPreset +{ + SUNNY = 1, + RAINY = 2, + CLOUDY = 3, } -public record SeasonalValues +public record PresetWeights { [JsonPropertyName("clouds")] - public WeatherSettings? Clouds { get; set; } + public Dictionary Clouds { get; set; } [JsonPropertyName("windSpeed")] public WeatherSettings? WindSpeed { get; set; } diff --git a/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs b/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs index 41bb4bf67..1d15bf61d 100644 --- a/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs @@ -6,6 +6,7 @@ using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Servers; using SPTarkov.Server.Core.Utils; +using SPTarkov.Server.Core.Utils.Cloners; namespace SPTarkov.Server.Core.Services; @@ -15,7 +16,8 @@ public class RaidWeatherService( WeatherGenerator weatherGenerator, SeasonalEventService seasonalEventService, WeightedRandomHelper weightedRandomHelper, - ConfigServer configServer + ConfigServer configServer, + ICloner cloner ) { protected readonly WeatherConfig WeatherConfig = configServer.GetConfig(); @@ -34,13 +36,17 @@ public void GenerateWeather(Season currentSeason) // Keep adding new weather until we have reached desired future date var nextTimestamp = startingTimestamp; + WeatherPreset? previousPreset = null; + var presetWeights = cloner.Clone(WeatherConfig.Weather.WeatherPresetWeight); while (nextTimestamp <= futureTimestampToReach) { - var newWeatherToAddToCache = weatherGenerator.GenerateWeather(currentSeason, nextTimestamp); + var newWeatherToAddToCache = weatherGenerator.GenerateWeather(currentSeason, ref presetWeights, nextTimestamp, previousPreset); // Add generated weather for time period to cache WeatherForecast.Add(newWeatherToAddToCache); + previousPreset = newWeatherToAddToCache.SptChosenPreset; + // Increment timestamp so next loop can begin at correct time nextTimestamp += GetWeightedWeatherTimePeriod(); } From abee0b9ee5bf4684c3ad7fa39362ad6ae5a10a10 Mon Sep 17 00:00:00 2001 From: Chomp Date: Mon, 29 Sep 2025 18:44:59 +0100 Subject: [PATCH 2/9] Moved generation logic around --- .../Controllers/WeatherController.cs | 17 +++++++++-- .../Generators/WeatherGenerator.cs | 29 +------------------ 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs b/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs index f98483be0..03c7b9c8e 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs @@ -1,21 +1,25 @@ using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Extensions; using SPTarkov.Server.Core.Generators; +using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Weather; -using SPTarkov.Server.Core.Models.Enums; using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Spt.Weather; using SPTarkov.Server.Core.Servers; using SPTarkov.Server.Core.Services; +using SPTarkov.Server.Core.Utils; using SPTarkov.Server.Core.Utils.Cloners; namespace SPTarkov.Server.Core.Controllers; [Injectable] public class WeatherController( + TimeUtil timeUtil, WeatherGenerator weatherGenerator, SeasonalEventService seasonalEventService, RaidWeatherService raidWeatherService, + WeatherHelper weatherHelper, ConfigServer configServer, ICloner cloner ) @@ -34,10 +38,17 @@ public WeatherData Generate() Time = string.Empty, Date = string.Empty, Weather = null, - Season = Season.AUTUMN, + Season = seasonalEventService.GetActiveWeatherSeason(), }; - weatherGenerator.CalculateGameTime(result); + var computedDate = timeUtil.GetDateTimeNow(); + var formattedDate = computedDate.FormatToBsgDate(); + + result.Date = formattedDate; + + //Get server uptime seconds multiplied by a multiplier and add to current time as seconds + result.Time = weatherHelper.GetInRaidTime().GetBsgFormattedWeatherTime(); + result.Acceleration = WeatherConfig.Acceleration; var presetWeights = cloner.Clone(WeatherConfig.Weather.WeatherPresetWeight); result.Weather = weatherGenerator.GenerateWeather(result.Season.Value, ref presetWeights); diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs index c3f1b282a..b11d7f90f 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs @@ -26,37 +26,10 @@ ICloner cloner { protected readonly WeatherConfig WeatherConfig = configServer.GetConfig(); - /// - /// Get current + raid datetime and format into correct BSG format. - /// - /// Weather data - /// WeatherData - public void CalculateGameTime(WeatherData data) - { - var computedDate = timeUtil.GetDateTimeNow(); - var formattedDate = computedDate.FormatToBsgDate(); - - data.Date = formattedDate; - data.Time = GetBsgFormattedInRaidTime(); - data.Acceleration = WeatherConfig.Acceleration; - - data.Season = seasonalEventService.GetActiveWeatherSeason(); - } - - /// - /// Get server uptime seconds multiplied by a multiplier and add to current time as seconds. - /// Formatted to BSGs requirements - /// - /// Formatted time as String - protected string GetBsgFormattedInRaidTime() - { - return weatherHelper.GetInRaidTime().GetBsgFormattedWeatherTime(); - } - /// /// Generate a weather object to send to client /// - /// Whaat season is weather being generated for + /// What season is weather being generated for /// Weather preset weights to pick from /// Optional - Current time /// Optional -What weather preset was last generated From ba386fe706a1e507acc435c35f364f1374e6e497 Mon Sep 17 00:00:00 2001 From: Chomp Date: Mon, 29 Sep 2025 18:47:35 +0100 Subject: [PATCH 3/9] Added seasonal variability support --- .../SPT_Data/configs/weather.json | 18 ++++++++++--- .../Controllers/WeatherController.cs | 5 ++-- .../Generators/WeatherGenerator.cs | 27 +++++++++++-------- .../Models/Spt/Config/WeatherConfig.cs | 2 +- .../Services/RaidWeatherService.cs | 2 +- 5 files changed, 36 insertions(+), 18 deletions(-) diff --git a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json index eaafa3962..084f10989 100644 --- a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json +++ b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json @@ -393,9 +393,21 @@ ] }, "weatherPresetWeight": { - "SUNNY": 8, - "RAINY": 8, - "CLOUDY": 8 + "WINTER_START": { + "SUNNY": 3, + "RAINY": 8, + "CLOUDY": 3 + }, + "WINTER_END": { + "SUNNY": 3, + "RAINY": 8, + "CLOUDY": 3 + }, + "default": { + "SUNNY": 8, + "RAINY": 8, + "CLOUDY": 8 + } } }, "seasonDates": [ diff --git a/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs b/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs index 03c7b9c8e..9aec5d240 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs @@ -32,13 +32,14 @@ ICloner cloner /// WeatherData public WeatherData Generate() { + var currentSeason = seasonalEventService.GetActiveWeatherSeason(); var result = new WeatherData { Acceleration = 0, Time = string.Empty, Date = string.Empty, Weather = null, - Season = seasonalEventService.GetActiveWeatherSeason(), + Season = currentSeason, }; var computedDate = timeUtil.GetDateTimeNow(); @@ -50,7 +51,7 @@ public WeatherData Generate() result.Time = weatherHelper.GetInRaidTime().GetBsgFormattedWeatherTime(); result.Acceleration = WeatherConfig.Acceleration; - var presetWeights = cloner.Clone(WeatherConfig.Weather.WeatherPresetWeight); + var presetWeights = cloner.Clone(weatherGenerator.GetWeatherPresetWeightsBySeason(currentSeason)); result.Weather = weatherGenerator.GenerateWeather(result.Season.Value, ref presetWeights); return result; diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs index b11d7f90f..966cfec65 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs @@ -6,7 +6,6 @@ using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Utils; using SPTarkov.Server.Core.Servers; -using SPTarkov.Server.Core.Services; using SPTarkov.Server.Core.Utils; using SPTarkov.Server.Core.Utils.Cloners; @@ -16,7 +15,6 @@ namespace SPTarkov.Server.Core.Generators; public class WeatherGenerator( ISptLogger logger, TimeUtil timeUtil, - SeasonalEventService seasonalEventService, WeatherHelper weatherHelper, ConfigServer configServer, WeightedRandomHelper weightedRandomHelper, @@ -41,18 +39,20 @@ public Weather GenerateWeather( WeatherPreset? previousPreset = null ) { - if (previousPreset is not null && presetWeights.Any()) + if (!presetWeights.Any()) + { + // Get fresh cloned weights from config + presetWeights = cloner.Clone(GetWeatherPresetWeightsBySeason(currentSeason)); + } + + // Only process when we have weights + there was previous preset chosen + if (previousPreset.HasValue) { // We know last picked preset, Adjust weights // Make it less likely to be picked now presetWeights[previousPreset.Value] -= 1; logger.Info($"{previousPreset.Value} weight reduced by: 1 to: {presetWeights[previousPreset.Value]}"); } - else - { - // Get fresh cloned weights from config - presetWeights = cloner.Clone(WeatherConfig.Weather.WeatherPresetWeight); - } // Assign value to previousPreset to be picked up next loop previousPreset = weightedRandomHelper.GetWeightedValue(presetWeights); @@ -62,17 +62,22 @@ public Weather GenerateWeather( if (presetWeights[previousPreset.Value] <= 0) { logger.Info($"{previousPreset.Value} is 0, resetting weights"); - // Force fresh presets to be picked + // Flag for fresh presets presetWeights.Clear(); } return GenerateWeatherByPreset(previousPreset.Value, currentSeason, timestamp); } - protected Weather GenerateWeatherByPreset(WeatherPreset chosenPreset, Season currentSeason, long? timestamp) + public Dictionary GetWeatherPresetWeightsBySeason(Season currentSeason) { - // TODO: handle currentSeason, apply additive values/overwrite existing? + return !WeatherConfig.Weather.WeatherPresetWeight.TryGetValue(currentSeason.ToString(), out var weights) + ? WeatherConfig.Weather.WeatherPresetWeight.GetValueOrDefault("default") + : weights; + } + protected Weather GenerateWeatherByPreset(WeatherPreset chosenPreset, Season currentSeason, long? timestamp) + { Weather result; var presetWeights = GetWeatherWeightsByPreset(chosenPreset); switch (chosenPreset) diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs index 03681038c..681017858 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs @@ -66,7 +66,7 @@ public record WeatherValues public WeatherSettings? TimePeriod { get; set; } [JsonPropertyName("weatherPresetWeight")] - public Dictionary WeatherPresetWeight { get; set; } + public Dictionary> WeatherPresetWeight { get; set; } } public enum WeatherPreset diff --git a/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs b/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs index 1d15bf61d..4be9153a8 100644 --- a/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs @@ -37,7 +37,7 @@ public void GenerateWeather(Season currentSeason) // Keep adding new weather until we have reached desired future date var nextTimestamp = startingTimestamp; WeatherPreset? previousPreset = null; - var presetWeights = cloner.Clone(WeatherConfig.Weather.WeatherPresetWeight); + var presetWeights = cloner.Clone(weatherGenerator.GetWeatherPresetWeightsBySeason(currentSeason)); while (nextTimestamp <= futureTimestampToReach) { var newWeatherToAddToCache = weatherGenerator.GenerateWeather(currentSeason, ref presetWeights, nextTimestamp, previousPreset); From 3a43618037a941ba53bc3a3a37d92f15e4f909a9 Mon Sep 17 00:00:00 2001 From: Chomp Date: Mon, 29 Sep 2025 19:25:10 +0100 Subject: [PATCH 4/9] Expanded weather generation to use DI system and allow easier modding --- .../AbstractWeatherPresetGeneratorBase.cs | 46 +++++++ .../WeatherGen/CloudyWeatherGenerator.cs | 41 ++++++ .../WeatherGen/RainyWeatherGenerator.cs | 41 ++++++ .../WeatherGen/SunnyWeatherGenerator.cs | 39 ++++++ .../Generators/WeatherGenerator.cs | 122 +----------------- .../Spt/Weather/IWeatherPresetGenerator.cs | 9 ++ 6 files changed, 181 insertions(+), 117 deletions(-) create mode 100644 Libraries/SPTarkov.Server.Core/Generators/WeatherGen/AbstractWeatherPresetGeneratorBase.cs create mode 100644 Libraries/SPTarkov.Server.Core/Generators/WeatherGen/CloudyWeatherGenerator.cs create mode 100644 Libraries/SPTarkov.Server.Core/Generators/WeatherGen/RainyWeatherGenerator.cs create mode 100644 Libraries/SPTarkov.Server.Core/Generators/WeatherGen/SunnyWeatherGenerator.cs create mode 100644 Libraries/SPTarkov.Server.Core/Models/Spt/Weather/IWeatherPresetGenerator.cs diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/AbstractWeatherPresetGeneratorBase.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/AbstractWeatherPresetGeneratorBase.cs new file mode 100644 index 000000000..02a06e32b --- /dev/null +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/AbstractWeatherPresetGeneratorBase.cs @@ -0,0 +1,46 @@ +using SPTarkov.Server.Core.Helpers; +using SPTarkov.Server.Core.Models.Eft.Weather; +using SPTarkov.Server.Core.Models.Enums; +using SPTarkov.Server.Core.Models.Spt.Config; +using SPTarkov.Server.Core.Models.Spt.Weather; +using SPTarkov.Server.Core.Utils; + +namespace SPTarkov.Server.Core.Generators.WeatherGen; + +public abstract record AbstractWeatherPresetGeneratorBase(WeightedRandomHelper WeightedRandomHelper, RandomUtil RandomUtil) + : IWeatherPresetGenerator +{ + public abstract bool CanHandle(WeatherPreset preset); + + public abstract Weather Generate(PresetWeights weatherWeights); + + protected WindDirection GetWeightedWindDirection(PresetWeights weather) + { + return WeightedRandomHelper.WeightedRandom(weather.WindDirection.Values, weather.WindDirection.Weights).Item; + } + + protected double GetWeightedClouds(PresetWeights weather) + { + return double.Parse(WeightedRandomHelper.GetWeightedValue(weather.Clouds)); + } + + protected double GetWeightedWindSpeed(PresetWeights weather) + { + return WeightedRandomHelper.WeightedRandom(weather.WindSpeed.Values, weather.WindSpeed.Weights).Item; + } + + protected double GetWeightedFog(PresetWeights weather) + { + return WeightedRandomHelper.WeightedRandom(weather.Fog.Values, weather.Fog.Weights).Item; + } + + protected double GetWeightedRain(PresetWeights weather) + { + return WeightedRandomHelper.WeightedRandom(weather.Rain.Values, weather.Rain.Weights).Item; + } + + protected double GetRandomDouble(double min, double max, int precision = 3) + { + return Math.Round(RandomUtil.GetDouble(min, max), precision); + } +} diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/CloudyWeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/CloudyWeatherGenerator.cs new file mode 100644 index 000000000..e126f9c49 --- /dev/null +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/CloudyWeatherGenerator.cs @@ -0,0 +1,41 @@ +using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Helpers; +using SPTarkov.Server.Core.Models.Eft.Weather; +using SPTarkov.Server.Core.Models.Spt.Config; +using SPTarkov.Server.Core.Utils; + +namespace SPTarkov.Server.Core.Generators.WeatherGen; + +[Injectable] +public record CloudyWeatherGenerator(WeightedRandomHelper WeightedRandomHelper, RandomUtil RandomUtil) + : AbstractWeatherPresetGeneratorBase(WeightedRandomHelper, RandomUtil) +{ + public override bool CanHandle(WeatherPreset preset) + { + return preset == WeatherPreset.CLOUDY; + } + + public override Weather Generate(PresetWeights weatherWeights) + { + var clouds = GetWeightedClouds(weatherWeights); + + var result = new Weather + { + Pressure = GetRandomDouble(weatherWeights.Pressure.Min, weatherWeights.Pressure.Max), + Temperature = 0, // Handled in caller + Fog = GetWeightedFog(weatherWeights), + RainIntensity = 0, + Rain = 0, + WindGustiness = GetRandomDouble(weatherWeights.WindGustiness.Min, weatherWeights.WindGustiness.Max, 2), + WindDirection = GetWeightedWindDirection(weatherWeights), + WindSpeed = GetWeightedWindSpeed(weatherWeights), + Cloud = clouds, + Time = string.Empty, + Date = string.Empty, + Timestamp = 0, + SptInRaidTimestamp = 0, // Handled in caller + }; + + return result; + } +} diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/RainyWeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/RainyWeatherGenerator.cs new file mode 100644 index 000000000..a979fa600 --- /dev/null +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/RainyWeatherGenerator.cs @@ -0,0 +1,41 @@ +using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Helpers; +using SPTarkov.Server.Core.Models.Eft.Weather; +using SPTarkov.Server.Core.Models.Spt.Config; +using SPTarkov.Server.Core.Utils; + +namespace SPTarkov.Server.Core.Generators.WeatherGen; + +[Injectable] +public record RainyWeatherGenerator(WeightedRandomHelper WeightedRandomHelper, RandomUtil RandomUtil) + : AbstractWeatherPresetGeneratorBase(WeightedRandomHelper, RandomUtil) +{ + public override bool CanHandle(WeatherPreset preset) + { + return preset == WeatherPreset.RAINY; + } + + public override Weather Generate(PresetWeights weatherWeights) + { + var clouds = GetWeightedClouds(weatherWeights); + + var result = new Weather + { + Pressure = GetRandomDouble(weatherWeights.Pressure.Min, weatherWeights.Pressure.Max), + Temperature = 0, // // Handled in caller + Fog = GetWeightedFog(weatherWeights), + RainIntensity = GetRandomDouble(weatherWeights.RainIntensity.Min, weatherWeights.RainIntensity.Max), + Rain = GetWeightedRain(weatherWeights), + WindGustiness = GetRandomDouble(weatherWeights.WindGustiness.Min, weatherWeights.WindGustiness.Max, 2), + WindDirection = GetWeightedWindDirection(weatherWeights), + WindSpeed = GetWeightedWindSpeed(weatherWeights), + Cloud = clouds, + Time = string.Empty, + Date = string.Empty, + Timestamp = 0, + SptInRaidTimestamp = 0, // Handled in caller + }; + + return result; + } +} diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/SunnyWeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/SunnyWeatherGenerator.cs new file mode 100644 index 000000000..8df81cbb8 --- /dev/null +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/SunnyWeatherGenerator.cs @@ -0,0 +1,39 @@ +using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Helpers; +using SPTarkov.Server.Core.Models.Eft.Weather; +using SPTarkov.Server.Core.Models.Spt.Config; +using SPTarkov.Server.Core.Utils; + +namespace SPTarkov.Server.Core.Generators.WeatherGen; + +[Injectable] +public record SunnyWeatherGenerator(WeightedRandomHelper WeightedRandomHelper, RandomUtil RandomUtil) + : AbstractWeatherPresetGeneratorBase(WeightedRandomHelper, RandomUtil) +{ + public override bool CanHandle(WeatherPreset preset) + { + return preset == WeatherPreset.SUNNY; + } + + public override Weather Generate(PresetWeights weatherWeights) + { + var result = new Weather + { + Pressure = GetRandomDouble(weatherWeights.Pressure.Min, weatherWeights.Pressure.Max), + Temperature = 0, // Handled in caller + Fog = GetWeightedFog(weatherWeights), + RainIntensity = 0, + Rain = 0, + WindGustiness = GetRandomDouble(weatherWeights.WindGustiness.Min, weatherWeights.WindGustiness.Max, 2), + WindDirection = GetWeightedWindDirection(weatherWeights), + WindSpeed = GetWeightedWindSpeed(weatherWeights), + Cloud = GetWeightedClouds(weatherWeights), + Time = string.Empty, + Date = string.Empty, + Timestamp = 0, + SptInRaidTimestamp = 0, // Handled in caller + }; + + return result; + } +} diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs index 966cfec65..ae2db758b 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs @@ -4,6 +4,7 @@ using SPTarkov.Server.Core.Models.Eft.Weather; using SPTarkov.Server.Core.Models.Enums; using SPTarkov.Server.Core.Models.Spt.Config; +using SPTarkov.Server.Core.Models.Spt.Weather; using SPTarkov.Server.Core.Models.Utils; using SPTarkov.Server.Core.Servers; using SPTarkov.Server.Core.Utils; @@ -19,6 +20,7 @@ public class WeatherGenerator( ConfigServer configServer, WeightedRandomHelper weightedRandomHelper, RandomUtil randomUtil, + IEnumerable weatherGenerators, ICloner cloner ) { @@ -78,24 +80,10 @@ public Dictionary GetWeatherPresetWeightsBySeason(Season protected Weather GenerateWeatherByPreset(WeatherPreset chosenPreset, Season currentSeason, long? timestamp) { - Weather result; + var generator = weatherGenerators.FirstOrDefault(generator => generator.CanHandle(chosenPreset)); + var presetWeights = GetWeatherWeightsByPreset(chosenPreset); - switch (chosenPreset) - { - case WeatherPreset.SUNNY: - result = GenerateSunnyWeather(presetWeights); - break; - case WeatherPreset.RAINY: - result = GenerateRainyWeather(presetWeights); - break; - case WeatherPreset.CLOUDY: - result = GenerateCloudyWeather(presetWeights); - break; - default: - presetWeights = GetWeatherWeightsByPreset(WeatherPreset.SUNNY); - result = GenerateSunnyWeather(presetWeights); - break; - } + var result = generator.Generate(presetWeights); // Set time values in result using now or passed in timestamp SetCurrentDateTime(result, timestamp); @@ -109,76 +97,6 @@ protected Weather GenerateWeatherByPreset(WeatherPreset chosenPreset, Season cur return result; } - protected Weather GenerateSunnyWeather(PresetWeights weatherWeights) - { - var result = new Weather - { - Pressure = GetRandomDouble(weatherWeights.Pressure.Min, weatherWeights.Pressure.Max), - Temperature = 0, // Handled in caller - Fog = GetWeightedFog(weatherWeights), - RainIntensity = 0, - Rain = 0, - WindGustiness = GetRandomDouble(weatherWeights.WindGustiness.Min, weatherWeights.WindGustiness.Max, 2), - WindDirection = GetWeightedWindDirection(weatherWeights), - WindSpeed = GetWeightedWindSpeed(weatherWeights), - Cloud = GetWeightedClouds(weatherWeights), - Time = string.Empty, - Date = string.Empty, - Timestamp = 0, - SptInRaidTimestamp = 0, // Handled in caller - }; - - return result; - } - - protected Weather GenerateRainyWeather(PresetWeights weatherWeights) - { - var clouds = GetWeightedClouds(weatherWeights); - - var result = new Weather - { - Pressure = GetRandomDouble(weatherWeights.Pressure.Min, weatherWeights.Pressure.Max), - Temperature = 0, // // Handled in caller - Fog = GetWeightedFog(weatherWeights), - RainIntensity = GetRandomDouble(weatherWeights.RainIntensity.Min, weatherWeights.RainIntensity.Max), - Rain = GetWeightedRain(weatherWeights), - WindGustiness = GetRandomDouble(weatherWeights.WindGustiness.Min, weatherWeights.WindGustiness.Max, 2), - WindDirection = GetWeightedWindDirection(weatherWeights), - WindSpeed = GetWeightedWindSpeed(weatherWeights), - Cloud = clouds, - Time = string.Empty, - Date = string.Empty, - Timestamp = 0, - SptInRaidTimestamp = 0, // Handled in caller - }; - - return result; - } - - protected Weather GenerateCloudyWeather(PresetWeights weatherWeights) - { - var clouds = GetWeightedClouds(weatherWeights); - - var result = new Weather - { - Pressure = GetRandomDouble(weatherWeights.Pressure.Min, weatherWeights.Pressure.Max), - Temperature = 0, // Handled in caller - Fog = GetWeightedFog(weatherWeights), - RainIntensity = 0, - Rain = 0, - WindGustiness = GetRandomDouble(weatherWeights.WindGustiness.Min, weatherWeights.WindGustiness.Max, 2), - WindDirection = GetWeightedWindDirection(weatherWeights), - WindSpeed = GetWeightedWindSpeed(weatherWeights), - Cloud = clouds, - Time = string.Empty, - Date = string.Empty, - Timestamp = 0, - SptInRaidTimestamp = 0, // Handled in caller - }; - - return result; - } - protected PresetWeights GetWeatherWeightsByPreset(WeatherPreset weatherPreset) { if (!WeatherConfig.Weather.PresetWeights.TryGetValue(weatherPreset.ToString(), out var value)) @@ -221,34 +139,4 @@ protected void SetCurrentDateTime(Weather weather, long? timestamp = null) weather.Time = datetimeBsgFormat; // matches weather.timestamp weather.SptInRaidTimestamp = weather.Timestamp; } - - protected WindDirection GetWeightedWindDirection(PresetWeights weather) - { - return weightedRandomHelper.WeightedRandom(weather.WindDirection.Values, weather.WindDirection.Weights).Item; - } - - protected double GetWeightedClouds(PresetWeights weather) - { - return double.Parse(weightedRandomHelper.GetWeightedValue(weather.Clouds)); - } - - protected double GetWeightedWindSpeed(PresetWeights weather) - { - return weightedRandomHelper.WeightedRandom(weather.WindSpeed.Values, weather.WindSpeed.Weights).Item; - } - - protected double GetWeightedFog(PresetWeights weather) - { - return weightedRandomHelper.WeightedRandom(weather.Fog.Values, weather.Fog.Weights).Item; - } - - protected double GetWeightedRain(PresetWeights weather) - { - return weightedRandomHelper.WeightedRandom(weather.Rain.Values, weather.Rain.Weights).Item; - } - - protected double GetRandomDouble(double min, double max, int precision = 3) - { - return Math.Round(randomUtil.GetDouble(min, max), precision); - } } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Weather/IWeatherPresetGenerator.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Weather/IWeatherPresetGenerator.cs new file mode 100644 index 000000000..4b8e9426e --- /dev/null +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Weather/IWeatherPresetGenerator.cs @@ -0,0 +1,9 @@ +using SPTarkov.Server.Core.Models.Spt.Config; + +namespace SPTarkov.Server.Core.Models.Spt.Weather; + +public interface IWeatherPresetGenerator +{ + public bool CanHandle(WeatherPreset preset); + public Eft.Weather.Weather Generate(PresetWeights weatherWeights); +} From 082ab8c6c9299755ee4341423c8da093acfdeb5f Mon Sep 17 00:00:00 2001 From: Chomp Date: Mon, 29 Sep 2025 19:53:23 +0100 Subject: [PATCH 5/9] Updated weather weight values Converted records into classes --- .../SPT_Data/configs/weather.json | 313 +++++------------- .../AbstractWeatherPresetGeneratorBase.cs | 14 +- .../WeatherGen/CloudyWeatherGenerator.cs | 4 +- .../WeatherGen/RainyWeatherGenerator.cs | 4 +- .../WeatherGen/SunnyWeatherGenerator.cs | 4 +- .../Models/Spt/Config/WeatherConfig.cs | 8 +- 6 files changed, 100 insertions(+), 247 deletions(-) diff --git a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json index 084f10989..c7a8fb2e0 100644 --- a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json +++ b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json @@ -9,74 +9,39 @@ "-0.8": 2 }, "windSpeed": { - "values": [ - 0, - 1, - 2, - 3, - 4 - ], - "weights": [ - 6, - 3, - 2, - 1, - 1 - ] + "0": 6, + "1": 3, + "2": 2, + "3": 1, + "4": 1 }, "windDirection": { - "values": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8 - ], - "weights": [ - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 - ] + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1 }, "windGustiness": { "min": 0, "max": 1 }, "rain": { - "values": [ - 1 - ], - "weights": [ - 1 - ] + "1": 1 }, "rainIntensity": { "min": 0, "max": 0 }, "fog": { - "values": [ - 0.0013, - 0.0018, - 0.002, - 0.004, - 0.006 - ], - "weights": [ - 35, - 6, - 4, - 3, - 1 - ] + "0.0013": 35, + "0.0018": 6, + "0.002": 4, + "0.004": 3, + "0.006": 1 }, "temp": { "day": { @@ -99,80 +64,42 @@ "1": 4 }, "windSpeed": { - "values": [ - 0, - 1, - 2, - 3, - 4 - ], - "weights": [ - 6, - 3, - 2, - 1, - 1 - ] + "0": 6, + "1": 3, + "2": 2, + "3": 1, + "4": 1 }, "windDirection": { - "values": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8 - ], - "weights": [ - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 - ] + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1 }, "windGustiness": { "min": 0, "max": 1 }, "rain": { - "values": [ - 2, - 3, - 4, - 5 - ], - "weights": [ - 5, - 5, - 5, - 5 - ] + "2": 5, + "3": 5, + "4": 5, + "5": 5 }, "rainIntensity": { "min": 0.1, "max": 1 }, "fog": { - "values": [ - 0.0013, - 0.0018, - 0.002, - 0.004, - 0.006 - ], - "weights": [ - 35, - 6, - 4, - 3, - 1 - ] + "0.0013": 35, + "0.0018": 6, + "0.002": 4, + "0.004": 3, + "0.006": 1 }, "temp": { "day": { @@ -198,74 +125,39 @@ "1": 10 }, "windSpeed": { - "values": [ - 0, - 1, - 2, - 3, - 4 - ], - "weights": [ - 6, - 3, - 2, - 1, - 1 - ] + "0": 6, + "1": 3, + "2": 2, + "3": 1, + "4": 1 }, "windDirection": { - "values": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8 - ], - "weights": [ - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 - ] + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1 }, "windGustiness": { "min": 0, "max": 1 }, "rain": { - "values": [ - 1 - ], - "weights": [ - 1 - ] + "1": 1 }, "rainIntensity": { "min": 0, "max": 1 }, "fog": { - "values": [ - 0.0013, - 0.0018, - 0.002, - 0.004, - 0.006 - ], - "weights": [ - 35, - 6, - 4, - 3, - 1 - ] + "0.0013": 35, + "0.0018": 6, + "0.002": 4, + "0.004": 3, + "0.006": 1 }, "temp": { "day": { @@ -289,82 +181,43 @@ "1": 1 }, "windSpeed": { - "values": [ - 0, - 1, - 2, - 3, - 4 - ], - "weights": [ - 6, - 3, - 2, - 1, - 1 - ] + "0": 6, + "1": 3, + "2": 2, + "3": 1, + "4": 1 }, "windDirection": { - "values": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8 - ], - "weights": [ - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 - ] + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + "8": 1 }, "windGustiness": { "min": 0, "max": 1 }, "rain": { - "values": [ - 1, - 2, - 3, - 4, - 5 - ], - "weights": [ - 0, - 1, - 1, - 1, - 1 - ] + "1": 0, + "2": 1, + "3": 1, + "4": 1, + "5": 1 }, "rainIntensity": { "min": 0, "max": 1 }, "fog": { - "values": [ - 0.0013, - 0.0018, - 0.002, - 0.004, - 0.012 - ], - "weights": [ - 5, - 4, - 1, - 3, - 2 - ] + "0.0013": 5, + "0.0018": 4, + "0.002": 1, + "0.004": 3, + "0.012": 2 }, "temp": { "day": { diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/AbstractWeatherPresetGeneratorBase.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/AbstractWeatherPresetGeneratorBase.cs index 02a06e32b..88e28cfd2 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/AbstractWeatherPresetGeneratorBase.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/AbstractWeatherPresetGeneratorBase.cs @@ -7,7 +7,7 @@ namespace SPTarkov.Server.Core.Generators.WeatherGen; -public abstract record AbstractWeatherPresetGeneratorBase(WeightedRandomHelper WeightedRandomHelper, RandomUtil RandomUtil) +public abstract class AbstractWeatherPresetGeneratorBase(WeightedRandomHelper weightedRandomHelper, RandomUtil randomUtil) : IWeatherPresetGenerator { public abstract bool CanHandle(WeatherPreset preset); @@ -16,31 +16,31 @@ public abstract record AbstractWeatherPresetGeneratorBase(WeightedRandomHelper W protected WindDirection GetWeightedWindDirection(PresetWeights weather) { - return WeightedRandomHelper.WeightedRandom(weather.WindDirection.Values, weather.WindDirection.Weights).Item; + return weightedRandomHelper.GetWeightedValue(weather.WindDirection); } protected double GetWeightedClouds(PresetWeights weather) { - return double.Parse(WeightedRandomHelper.GetWeightedValue(weather.Clouds)); + return double.Parse(weightedRandomHelper.GetWeightedValue(weather.Clouds)); } protected double GetWeightedWindSpeed(PresetWeights weather) { - return WeightedRandomHelper.WeightedRandom(weather.WindSpeed.Values, weather.WindSpeed.Weights).Item; + return double.Parse(weightedRandomHelper.GetWeightedValue(weather.WindSpeed)); } protected double GetWeightedFog(PresetWeights weather) { - return WeightedRandomHelper.WeightedRandom(weather.Fog.Values, weather.Fog.Weights).Item; + return double.Parse(weightedRandomHelper.GetWeightedValue(weather.Fog)); } protected double GetWeightedRain(PresetWeights weather) { - return WeightedRandomHelper.WeightedRandom(weather.Rain.Values, weather.Rain.Weights).Item; + return double.Parse(weightedRandomHelper.GetWeightedValue(weather.Rain)); } protected double GetRandomDouble(double min, double max, int precision = 3) { - return Math.Round(RandomUtil.GetDouble(min, max), precision); + return Math.Round(randomUtil.GetDouble(min, max), precision); } } diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/CloudyWeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/CloudyWeatherGenerator.cs index e126f9c49..658212b7d 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/CloudyWeatherGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/CloudyWeatherGenerator.cs @@ -7,8 +7,8 @@ namespace SPTarkov.Server.Core.Generators.WeatherGen; [Injectable] -public record CloudyWeatherGenerator(WeightedRandomHelper WeightedRandomHelper, RandomUtil RandomUtil) - : AbstractWeatherPresetGeneratorBase(WeightedRandomHelper, RandomUtil) +public class CloudyWeatherGenerator(WeightedRandomHelper weightedRandomHelper, RandomUtil randomUtil) + : AbstractWeatherPresetGeneratorBase(weightedRandomHelper, randomUtil) { public override bool CanHandle(WeatherPreset preset) { diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/RainyWeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/RainyWeatherGenerator.cs index a979fa600..f50daa4be 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/RainyWeatherGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/RainyWeatherGenerator.cs @@ -7,8 +7,8 @@ namespace SPTarkov.Server.Core.Generators.WeatherGen; [Injectable] -public record RainyWeatherGenerator(WeightedRandomHelper WeightedRandomHelper, RandomUtil RandomUtil) - : AbstractWeatherPresetGeneratorBase(WeightedRandomHelper, RandomUtil) +public class RainyWeatherGenerator(WeightedRandomHelper weightedRandomHelper, RandomUtil randomUtil) + : AbstractWeatherPresetGeneratorBase(weightedRandomHelper, randomUtil) { public override bool CanHandle(WeatherPreset preset) { diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/SunnyWeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/SunnyWeatherGenerator.cs index 8df81cbb8..048bcfcaf 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/SunnyWeatherGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGen/SunnyWeatherGenerator.cs @@ -7,8 +7,8 @@ namespace SPTarkov.Server.Core.Generators.WeatherGen; [Injectable] -public record SunnyWeatherGenerator(WeightedRandomHelper WeightedRandomHelper, RandomUtil RandomUtil) - : AbstractWeatherPresetGeneratorBase(WeightedRandomHelper, RandomUtil) +public class SunnyWeatherGenerator(WeightedRandomHelper weightedRandomHelper, RandomUtil randomUtil) + : AbstractWeatherPresetGeneratorBase(weightedRandomHelper, randomUtil) { public override bool CanHandle(WeatherPreset preset) { diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs index 681017858..020a272f4 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/WeatherConfig.cs @@ -82,22 +82,22 @@ public record PresetWeights public Dictionary Clouds { get; set; } [JsonPropertyName("windSpeed")] - public WeatherSettings? WindSpeed { get; set; } + public Dictionary? WindSpeed { get; set; } [JsonPropertyName("windDirection")] - public WeatherSettings? WindDirection { get; set; } + public Dictionary? WindDirection { get; set; } [JsonPropertyName("windGustiness")] public MinMax? WindGustiness { get; set; } [JsonPropertyName("rain")] - public WeatherSettings? Rain { get; set; } + public Dictionary? Rain { get; set; } [JsonPropertyName("rainIntensity")] public MinMax? RainIntensity { get; set; } [JsonPropertyName("fog")] - public WeatherSettings? Fog { get; set; } + public Dictionary? Fog { get; set; } [JsonPropertyName("temp")] public TempDayNight? Temp { get; set; } From c6360594705fe8ae95b878bf63124ee9c60456ee Mon Sep 17 00:00:00 2001 From: Chomp Date: Mon, 29 Sep 2025 20:05:02 +0100 Subject: [PATCH 6/9] Added fallback when generator isn't found --- .../Generators/WeatherGenerator.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs index ae2db758b..5f3bbb355 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs @@ -68,7 +68,7 @@ public Weather GenerateWeather( presetWeights.Clear(); } - return GenerateWeatherByPreset(previousPreset.Value, currentSeason, timestamp); + return GenerateWeatherByPreset(previousPreset.Value, timestamp); } public Dictionary GetWeatherPresetWeightsBySeason(Season currentSeason) @@ -78,9 +78,15 @@ public Dictionary GetWeatherPresetWeightsBySeason(Season : weights; } - protected Weather GenerateWeatherByPreset(WeatherPreset chosenPreset, Season currentSeason, long? timestamp) + protected Weather GenerateWeatherByPreset(WeatherPreset chosenPreset, long? timestamp) { var generator = weatherGenerators.FirstOrDefault(generator => generator.CanHandle(chosenPreset)); + if (generator is null) + { + logger.Warning($"Unable to find weather generator for: {chosenPreset}, falling back to sunny"); + + generator = weatherGenerators.FirstOrDefault(generator => generator.CanHandle(WeatherPreset.SUNNY)); + } var presetWeights = GetWeatherWeightsByPreset(chosenPreset); var result = generator.Generate(presetWeights); From beeece75b42dacedbb34e7d2dccc1a4386047dff Mon Sep 17 00:00:00 2001 From: Chomp Date: Mon, 29 Sep 2025 20:14:52 +0100 Subject: [PATCH 7/9] Fixed colliding lambda Added method comments --- .../Generators/WeatherGenerator.cs | 31 +++++++++++++------ .../Services/RaidWeatherService.cs | 4 +++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs index 5f3bbb355..4dc3f81c9 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs @@ -71,21 +71,32 @@ public Weather GenerateWeather( return GenerateWeatherByPreset(previousPreset.Value, timestamp); } + /// + /// Get weather property weights for the provided season + /// + /// Desired season to get weights for + /// Dictionary public Dictionary GetWeatherPresetWeightsBySeason(Season currentSeason) { return !WeatherConfig.Weather.WeatherPresetWeight.TryGetValue(currentSeason.ToString(), out var weights) - ? WeatherConfig.Weather.WeatherPresetWeight.GetValueOrDefault("default") + ? WeatherConfig.Weather.WeatherPresetWeight.GetValueOrDefault("default")! : weights; } + /// + /// Create a Weather object that adheres to the chosenPreset value + /// + /// The weather preset chosen to generate + /// OPTIONAL - generate the weapon object with a specific time instead of now + /// Weather protected Weather GenerateWeatherByPreset(WeatherPreset chosenPreset, long? timestamp) { - var generator = weatherGenerators.FirstOrDefault(generator => generator.CanHandle(chosenPreset)); + var generator = weatherGenerators.FirstOrDefault(gen => gen.CanHandle(chosenPreset)); if (generator is null) { logger.Warning($"Unable to find weather generator for: {chosenPreset}, falling back to sunny"); - generator = weatherGenerators.FirstOrDefault(generator => generator.CanHandle(WeatherPreset.SUNNY)); + generator = weatherGenerators.FirstOrDefault(gen => gen.CanHandle(WeatherPreset.SUNNY)); } var presetWeights = GetWeatherWeightsByPreset(chosenPreset); @@ -103,14 +114,16 @@ protected Weather GenerateWeatherByPreset(WeatherPreset chosenPreset, long? time return result; } + /// + /// Get the weather preset weights based on passed in preset, get defaults if preset not found in config + /// + /// Desired preset + /// PresetWeights protected PresetWeights GetWeatherWeightsByPreset(WeatherPreset weatherPreset) { - if (!WeatherConfig.Weather.PresetWeights.TryGetValue(weatherPreset.ToString(), out var value)) - { - return WeatherConfig.Weather.PresetWeights["default"]; - } - - return value; + return WeatherConfig.Weather.PresetWeights.TryGetValue(weatherPreset.ToString(), out var value) + ? value + : WeatherConfig.Weather.PresetWeights["default"]; } /// diff --git a/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs b/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs index 4be9153a8..96200f703 100644 --- a/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs @@ -36,15 +36,19 @@ public void GenerateWeather(Season currentSeason) // Keep adding new weather until we have reached desired future date var nextTimestamp = startingTimestamp; + + // Store this so it can be passed into GenerateWeather() WeatherPreset? previousPreset = null; var presetWeights = cloner.Clone(weatherGenerator.GetWeatherPresetWeightsBySeason(currentSeason)); while (nextTimestamp <= futureTimestampToReach) { + // Pass by ref as method will alter weight values var newWeatherToAddToCache = weatherGenerator.GenerateWeather(currentSeason, ref presetWeights, nextTimestamp, previousPreset); // Add generated weather for time period to cache WeatherForecast.Add(newWeatherToAddToCache); + // Store for use in next loop previousPreset = newWeatherToAddToCache.SptChosenPreset; // Increment timestamp so next loop can begin at correct time From c3cf8cac393bc97d364bb45f61cba3b39a75a92e Mon Sep 17 00:00:00 2001 From: Chomp Date: Tue, 30 Sep 2025 13:19:25 +0100 Subject: [PATCH 8/9] Cleanup of weather code --- .../Controllers/WeatherController.cs | 10 ++--- .../Generators/WeatherGenerator.cs | 38 +++++++++---------- .../Services/PostDbLoadService.cs | 2 +- .../Services/RaidWeatherService.cs | 4 +- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs b/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs index 9aec5d240..9512ba3c0 100644 --- a/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs +++ b/Libraries/SPTarkov.Server.Core/Controllers/WeatherController.cs @@ -33,6 +33,8 @@ ICloner cloner public WeatherData Generate() { var currentSeason = seasonalEventService.GetActiveWeatherSeason(); + + // Prep object to send to client var result = new WeatherData { Acceleration = 0, @@ -42,12 +44,10 @@ public WeatherData Generate() Season = currentSeason, }; - var computedDate = timeUtil.GetDateTimeNow(); - var formattedDate = computedDate.FormatToBsgDate(); - - result.Date = formattedDate; + // Assign now in a bsg-style formatted string to result object property + result.Date = timeUtil.GetDateTimeNow().FormatToBsgDate(); - //Get server uptime seconds multiplied by a multiplier and add to current time as seconds + // Get server uptime seconds multiplied by a multiplier and add to current time as seconds result.Time = weatherHelper.GetInRaidTime().GetBsgFormattedWeatherTime(); result.Acceleration = WeatherConfig.Acceleration; diff --git a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs index 4dc3f81c9..8120f07f3 100644 --- a/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs +++ b/Libraries/SPTarkov.Server.Core/Generators/WeatherGenerator.cs @@ -30,10 +30,10 @@ ICloner cloner /// Generate a weather object to send to client /// /// What season is weather being generated for - /// Weather preset weights to pick from - /// Optional - Current time + /// Weather preset weights to pick from (values will be altered when generating more than 1) + /// Optional - Current time in millisecond ticks /// Optional -What weather preset was last generated - /// Weather + /// A generated object public Weather GenerateWeather( Season currentSeason, ref Dictionary presetWeights, @@ -41,29 +41,27 @@ public Weather GenerateWeather( WeatherPreset? previousPreset = null ) { - if (!presetWeights.Any()) + if (presetWeights.Count == 0) { - // Get fresh cloned weights from config + // No presets, get fresh cloned weights from config presetWeights = cloner.Clone(GetWeatherPresetWeightsBySeason(currentSeason)); } // Only process when we have weights + there was previous preset chosen - if (previousPreset.HasValue) + if (previousPreset.HasValue && presetWeights.ContainsKey(previousPreset.Value)) { // We know last picked preset, Adjust weights // Make it less likely to be picked now - presetWeights[previousPreset.Value] -= 1; - logger.Info($"{previousPreset.Value} weight reduced by: 1 to: {presetWeights[previousPreset.Value]}"); + // Clamp to 0 + presetWeights[previousPreset.Value] = Math.Max(0, presetWeights[previousPreset.Value] - 1); } // Assign value to previousPreset to be picked up next loop previousPreset = weightedRandomHelper.GetWeightedValue(presetWeights); - logger.Warning($"Chose: {previousPreset}"); // Check if chosen preset has been exhausted and reset if necessary - if (presetWeights[previousPreset.Value] <= 0) + if (presetWeights[previousPreset.Value] == 0) { - logger.Info($"{previousPreset.Value} is 0, resetting weights"); // Flag for fresh presets presetWeights.Clear(); } @@ -72,23 +70,23 @@ public Weather GenerateWeather( } /// - /// Get weather property weights for the provided season + /// Gets weather property weights for the provided season /// /// Desired season to get weights for - /// Dictionary + /// A dictionary of weather preset weights public Dictionary GetWeatherPresetWeightsBySeason(Season currentSeason) { - return !WeatherConfig.Weather.WeatherPresetWeight.TryGetValue(currentSeason.ToString(), out var weights) - ? WeatherConfig.Weather.WeatherPresetWeight.GetValueOrDefault("default")! - : weights; + return WeatherConfig.Weather.WeatherPresetWeight.TryGetValue(currentSeason.ToString(), out var weights) + ? weights + : WeatherConfig.Weather.WeatherPresetWeight.GetValueOrDefault("default")!; } /// - /// Create a Weather object that adheres to the chosenPreset value + /// Creates a object that adheres to the chosen preset /// /// The weather preset chosen to generate - /// OPTIONAL - generate the weapon object with a specific time instead of now - /// Weather + /// OPTIONAL - generate the weather object with a specific time instead of now + /// A generated object protected Weather GenerateWeatherByPreset(WeatherPreset chosenPreset, long? timestamp) { var generator = weatherGenerators.FirstOrDefault(gen => gen.CanHandle(chosenPreset)); @@ -105,7 +103,7 @@ protected Weather GenerateWeatherByPreset(WeatherPreset chosenPreset, long? time // Set time values in result using now or passed in timestamp SetCurrentDateTime(result, timestamp); - // Must occur after SetCurrentDateTime() + // Must occur after SetCurrentDateTime(), temp depends on timestamp result.Temperature = GetRaidTemperature(presetWeights, result.SptInRaidTimestamp ?? 0); // Needed by RaidWeatherService diff --git a/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs b/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs index 79e86c0d3..6c46cba1d 100644 --- a/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs @@ -118,7 +118,7 @@ public void PerformPostDbLoadActions() AddCustomItemPresetsToGlobals(); var currentSeason = seasonalEventService.GetActiveWeatherSeason(); - raidWeatherService.GenerateWeather(currentSeason); + raidWeatherService.GenerateFutureWeatherAndCache(currentSeason); if (BotConfig.WeeklyBoss.Enabled) { diff --git a/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs b/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs index 96200f703..018ee2459 100644 --- a/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/RaidWeatherService.cs @@ -26,7 +26,7 @@ ICloner cloner /// /// Generate 24 hours of weather data starting from midnight today /// - public void GenerateWeather(Season currentSeason) + public void GenerateFutureWeatherAndCache(Season currentSeason) { // When to start generating weather from in milliseconds var startingTimestamp = timeUtil.GetTodayMidnightTimeStamp(); @@ -103,7 +103,7 @@ protected void ValidateWeatherDataExists(Season currentSeason) var result = WeatherForecast.Where(weather => weather.Timestamp >= timeUtil.GetTimeStamp()); if (!result.Any()) { - GenerateWeather(currentSeason); + GenerateFutureWeatherAndCache(currentSeason); } } } From 7b8c94984890c78944c2a0449e0e6207410d6a8c Mon Sep 17 00:00:00 2001 From: Chomp Date: Tue, 30 Sep 2025 13:22:43 +0100 Subject: [PATCH 9/9] Adjusted `weatherPresetWeight` values --- .../SPTarkov.Server.Assets/SPT_Data/configs/weather.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json index c7a8fb2e0..f9636d810 100644 --- a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json +++ b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/weather.json @@ -257,9 +257,9 @@ "CLOUDY": 3 }, "default": { - "SUNNY": 8, - "RAINY": 8, - "CLOUDY": 8 + "SUNNY": 7, + "RAINY": 7, + "CLOUDY": 7 } } },