From de36bd9f2c1baab2439cd3df8aa3d1554c36c6b1 Mon Sep 17 00:00:00 2001 From: KaenoDev <193943350+KaenoDev@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:50:47 +0000 Subject: [PATCH 1/3] Implement GenerateWeather and update getInRaidTime to match Ts server output --- Core/Generators/WeatherGenerator.cs | 79 +++++++++++++++++++++++------ Core/Helpers/WeatherHelper.cs | 10 ++-- Core/Utils/TimeUtil.cs | 12 +++++ 3 files changed, 82 insertions(+), 19 deletions(-) diff --git a/Core/Generators/WeatherGenerator.cs b/Core/Generators/WeatherGenerator.cs index bd254ace..badb981c 100644 --- a/Core/Generators/WeatherGenerator.cs +++ b/Core/Generators/WeatherGenerator.cs @@ -16,19 +16,25 @@ public class WeatherGenerator private readonly SeasonalEventService _seasonalEventService; private readonly WeatherHelper _weatherHelper; private readonly ConfigServer _configServer; - + private readonly WeightedRandomHelper _weightedRandomHelper; + private readonly RandomUtil _randomUtil; private readonly WeatherConfig _weatherConfig; public WeatherGenerator( TimeUtil timeUtil, SeasonalEventService seasonalEventService, WeatherHelper weatherHelper, - ConfigServer configServer) + ConfigServer configServer, + WeightedRandomHelper weightedRandomHelper, + RandomUtil randomUtil + ) { _timeUtil = timeUtil; _seasonalEventService = seasonalEventService; _weatherHelper = weatherHelper; _configServer = configServer; + _weightedRandomHelper = weightedRandomHelper; + _randomUtil = randomUtil; _weatherConfig = _configServer.GetConfig(ConfigTypes.WEATHER); } @@ -81,7 +87,36 @@ public class WeatherGenerator */ public Weather GenerateWeather(Season currentSeason, long? timestamp = null) { - throw new NotImplementedException(); + var weatherValues = GetWeatherValuesBySeason(currentSeason); + var clouds = GetWeightedClouds(weatherValues); + + // Force rain to off if no clouds + var rain = clouds <= 0.6 ? 0 : GetWeightedRain(weatherValues); + + // 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 ?? 0, weatherValues.Pressure.Max ?? 0), + Temperature = 0, + Fog = GetWeightedFog(weatherValues), + RainIntensity = + rain > 1 ? GetRandomDouble(weatherValues.RainIntensity.Min ?? 0, weatherValues.RainIntensity.Max ?? 0) : 0, + Rain = rain, + WindGustiness = GetRandomDouble(weatherValues.WindGustiness.Min ?? 0, weatherValues.WindGustiness.Max ?? 0, 2), + WindDirection = GetWeightedWindDirection(weatherValues), + WindSpeed = GetWeightedWindSpeed(weatherValues), + Cloud = clouds, + Time = "", + Date = "", + Timestamp = 0, + SptInRaidTimestamp = 0 + }; + + SetCurrentDateTime(result, timestamp); + + result.Temperature = GetRaidTemperature(weatherValues, result.SptInRaidTimestamp ?? 0); + + return result; } protected SeasonalValues GetWeatherValuesBySeason(Season currentSeason) @@ -92,7 +127,7 @@ public class WeatherGenerator return this._weatherConfig.Weather.SeasonValues["default"]; } - return value; + return value!; } /** @@ -101,9 +136,15 @@ public class WeatherGenerator * @param inRaidTimestamp What time is the raid running at * @returns Timestamp */ - protected double GetRaidTemperature(SeasonalValues weather, int inRaidTimestamp) + protected double GetRaidTemperature(SeasonalValues weather, long inRaidTimestamp) { - throw new NotImplementedException(); + // Convert timestamp to date so we can get current hour and check if its day or night + var currentRaidTime = new DateTime(inRaidTimestamp); + var minMax = _weatherHelper.IsHourAtNightTime(currentRaidTime.Hour) + ? weather.Temp.Night + : weather.Temp.Day; + + return Math.Round(_randomUtil.GetDouble(minMax.Min ?? 0, minMax.Max ?? 0), 2); } /** @@ -111,38 +152,46 @@ public class WeatherGenerator * @param weather Object to update * @param timestamp OPTIONAL, define timestamp used */ - protected void SetCurrentDateTime(Weather weather, int? timestamp = null) + protected void SetCurrentDateTime(Weather weather, long? timestamp = null) { - throw new NotImplementedException(); + var inRaidTime = _weatherHelper.GetInRaidTime(timestamp); + var normalTime = GetBsgFormattedTime(inRaidTime); + var formattedDate = _timeUtil.FormatDate(timestamp.HasValue ? _timeUtil.GetDateTimeFromTimeStamp(timestamp.Value) : DateTime.UtcNow); + var datetimeBsgFormat = $"{formattedDate} {normalTime}"; + + weather.Timestamp = timestamp ?? _timeUtil.GetTimeStampFromEpoch(inRaidTime); // matches weather.date We use to divide by 1000 + weather.Date = formattedDate; // matches weather.timestamp + weather.Time = datetimeBsgFormat; // matches weather.timestamp + weather.SptInRaidTimestamp = _timeUtil.GetTimeStampFromEpoch(inRaidTime); } protected WindDirection GetWeightedWindDirection(SeasonalValues weather) { - throw new NotImplementedException(); + return _weightedRandomHelper.WeightedRandom(weather.WindDirection.Values, weather.WindDirection.Weights).Item; } protected double GetWeightedClouds(SeasonalValues weather) { - throw new NotImplementedException(); + return _weightedRandomHelper.WeightedRandom(weather.Clouds.Values, weather.Clouds.Weights).Item; } protected double GetWeightedWindSpeed(SeasonalValues weather) { - throw new NotImplementedException(); + return _weightedRandomHelper.WeightedRandom(weather.WindSpeed.Values, weather.WindSpeed.Weights).Item; } protected double GetWeightedFog(SeasonalValues weather) { - throw new NotImplementedException(); + return _weightedRandomHelper.WeightedRandom(weather.Fog.Values, weather.Fog.Weights).Item; } protected double GetWeightedRain(SeasonalValues weather) { - throw new NotImplementedException(); + return _weightedRandomHelper.WeightedRandom(weather.Rain.Values, weather.Rain.Weights).Item; } - protected double GetRandomFloat(double min, double max, int precision = 3) + protected double GetRandomDouble(double min, double max, int precision = 3) { - throw new NotImplementedException(); + return Math.Round(_randomUtil.GetDouble(min, max), precision); } } diff --git a/Core/Helpers/WeatherHelper.cs b/Core/Helpers/WeatherHelper.cs index 0b3163f4..52987f03 100644 --- a/Core/Helpers/WeatherHelper.cs +++ b/Core/Helpers/WeatherHelper.cs @@ -40,11 +40,13 @@ public class WeatherHelper // tarkov time = (real time * 7 % 24 hr) + 3 hour var russiaOffsetMilliseconds = _timeUtil.GetHoursAsSeconds(3) * 1000; var twentyFourHoursMilliseconds = _timeUtil.GetHoursAsSeconds(24) * 1000; - var currentTimestampMilliSeconds = (timestamp is not null) ? timestamp : _timeUtil.GetTimeStamp(); + var currentTimestampMilliSeconds = timestamp.HasValue + ? timestamp ?? 0 + : (DateTime.UtcNow - DateTime.UnixEpoch).TotalMilliseconds; //_timeUtil.GetTimeStampFromEpoch(); - return new DateTime().AddMilliseconds( - (russiaOffsetMilliseconds + russiaOffsetMilliseconds * _weatherConfig.Acceleration) % - twentyFourHoursMilliseconds); + return _timeUtil.GetDateTimeFromTimeStamp((long) + (russiaOffsetMilliseconds + currentTimestampMilliSeconds * _weatherConfig.Acceleration) % + twentyFourHoursMilliseconds); } /// diff --git a/Core/Utils/TimeUtil.cs b/Core/Utils/TimeUtil.cs index eebc000d..2df541d8 100644 --- a/Core/Utils/TimeUtil.cs +++ b/Core/Utils/TimeUtil.cs @@ -184,4 +184,16 @@ public class TimeUtil { return DateTimeOffset.FromUnixTimeMilliseconds(timeStamp).DateTime; } + + /// + /// Takes a timestamp and gets difference between Epoch time and time provided resulting in a unixtimestamp (date defaults to utcnow) + /// + /// + /// + public long GetTimeStampFromEpoch(DateTime? date = null) + { + var dateToCompare = date ?? DateTime.UtcNow; + return (long)(dateToCompare - DateTime.UnixEpoch).TotalSeconds; + } + } From 826a4632899aedc3c0c288fe453a35cb754f179e Mon Sep 17 00:00:00 2001 From: KaenoDev <193943350+KaenoDev@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:53:18 +0000 Subject: [PATCH 2/3] Remove comment --- Core/Helpers/WeatherHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Helpers/WeatherHelper.cs b/Core/Helpers/WeatherHelper.cs index 52987f03..56c26435 100644 --- a/Core/Helpers/WeatherHelper.cs +++ b/Core/Helpers/WeatherHelper.cs @@ -42,7 +42,7 @@ public class WeatherHelper var twentyFourHoursMilliseconds = _timeUtil.GetHoursAsSeconds(24) * 1000; var currentTimestampMilliSeconds = timestamp.HasValue ? timestamp ?? 0 - : (DateTime.UtcNow - DateTime.UnixEpoch).TotalMilliseconds; //_timeUtil.GetTimeStampFromEpoch(); + : (DateTime.UtcNow - DateTime.UnixEpoch).TotalMilliseconds; return _timeUtil.GetDateTimeFromTimeStamp((long) (russiaOffsetMilliseconds + currentTimestampMilliSeconds * _weatherConfig.Acceleration) % From 0d1feb801702caa7f06280a65141b0c56461e4cd Mon Sep 17 00:00:00 2001 From: CWX Date: Tue, 14 Jan 2025 18:02:14 +0000 Subject: [PATCH 3/3] fix services and botgen level being null --- Core/Generators/BotLevelGenerator.cs | 26 ++++++++++++++++---------- Core/Helpers/ItemHelper.cs | 4 ++-- Core/Helpers/PresetHelper.cs | 2 +- Core/Services/MailSendService.cs | 2 +- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Core/Generators/BotLevelGenerator.cs b/Core/Generators/BotLevelGenerator.cs index d074ef8a..e3efb15f 100644 --- a/Core/Generators/BotLevelGenerator.cs +++ b/Core/Generators/BotLevelGenerator.cs @@ -43,7 +43,8 @@ public class BotLevelGenerator // Get random level based on the exp table. int exp = 0; - var level = int.Parse(ChooseBotLevel(botLevelRange.Min.Value, botLevelRange.Max.Value, 1, 1.15).ToString()); // TODO - nasty double to string to int conversion + var level = int.Parse(ChooseBotLevel(botLevelRange.Min.Value, botLevelRange.Max.Value, 1, 1.15) + .ToString()); // TODO - nasty double to string to int conversion for (var i = 0; i < level; i++) { exp += expTable[i].Experience.Value; @@ -55,7 +56,7 @@ public class BotLevelGenerator exp += _randomUtil.GetInt(0, expTable[level].Experience.Value - 1); } - return new RandomisedBotLevelResult{ Level = level, Exp = exp }; + return new RandomisedBotLevelResult { Level = level, Exp = exp }; } public double ChooseBotLevel(double min, double max, int shift, double number) @@ -76,24 +77,29 @@ public class BotLevelGenerator var pmcOverride = botGenerationDetails.LocationSpecificPmcLevelOverride; var minPossibleLevel = isPmc && pmcOverride is not null - ? Math.Min( - Math.Max(levelDetails.Min.Value, pmcOverride.Min.Value), // Biggest between json min and the botgen min - maxAvailableLevel // Fallback if value above is crazy (default is 79) - ) - : Math.Min(levelDetails.Min.Value, maxAvailableLevel); // Not pmc with override or non-pmc + ? Math.Min( + Math.Max(levelDetails.Min.Value, pmcOverride.Min.Value), // Biggest between json min and the botgen min + maxAvailableLevel // Fallback if value above is crazy (default is 79) + ) + : Math.Min(levelDetails.Min.Value, maxAvailableLevel); // Not pmc with override or non-pmc var maxPossibleLevel = isPmc && pmcOverride is not null ? Math.Min(pmcOverride.Max.Value, maxAvailableLevel) // Was a PMC and they have a level override : Math.Min(levelDetails.Max.Value, maxAvailableLevel); // Not pmc with override or non-pmc - var minLevel = botGenerationDetails.PlayerLevel.Value - botGenerationDetails.BotRelativeLevelDeltaMin.Value; - var maxLevel = botGenerationDetails.PlayerLevel.Value + botGenerationDetails.BotRelativeLevelDeltaMin.Value; + var minLevel = botGenerationDetails.PlayerLevel.HasValue + ? botGenerationDetails.PlayerLevel.Value + : 0 - botGenerationDetails.BotRelativeLevelDeltaMin.Value; + var maxLevel = botGenerationDetails.PlayerLevel.HasValue + ? botGenerationDetails.PlayerLevel.Value + : 0 + botGenerationDetails.BotRelativeLevelDeltaMin.Value; // Bound the level to the min/max possible maxLevel = Math.Min(Math.Max(maxLevel, minPossibleLevel), maxPossibleLevel); minLevel = Math.Min(Math.Max(minLevel, minPossibleLevel), maxPossibleLevel); - return new MinMax{ + return new MinMax + { Min = minLevel, Max = maxLevel, }; diff --git a/Core/Helpers/ItemHelper.cs b/Core/Helpers/ItemHelper.cs index e4aadf99..313af33f 100644 --- a/Core/Helpers/ItemHelper.cs +++ b/Core/Helpers/ItemHelper.cs @@ -1044,9 +1044,9 @@ public class ItemHelper throw new NotImplementedException(); } - public bool IsOfBaseclass(string valueEncyclopedia, string weapon) + public bool IsOfBaseclass(string tpl, List baseClassTpls) { - throw new NotImplementedException(); + return _itemBaseClassService.ItemHasBaseClass(tpl, baseClassTpls); } } diff --git a/Core/Helpers/PresetHelper.cs b/Core/Helpers/PresetHelper.cs index 08bee62d..950eb063 100644 --- a/Core/Helpers/PresetHelper.cs +++ b/Core/Helpers/PresetHelper.cs @@ -57,7 +57,7 @@ public class PresetHelper var tempPresets = _databaseService.GetGlobals().ItemPresets; tempPresets = tempPresets.Where(p => p.Value.Encyclopedia != null && - _itemHelper.IsOfBaseclass(p.Value.Encyclopedia, BaseClasses.WEAPON)).ToDictionary(); + _itemHelper.IsOfBaseclass(p.Value.Encyclopedia, [BaseClasses.WEAPON])).ToDictionary(); } return _defaultWeaponPresets; diff --git a/Core/Services/MailSendService.cs b/Core/Services/MailSendService.cs index aa929b37..3b9bef99 100644 --- a/Core/Services/MailSendService.cs +++ b/Core/Services/MailSendService.cs @@ -450,7 +450,7 @@ public class MailSendService } // Boxes can contain sub-items - if (_itemHelper.IsOfBaseclass(itemTemplate.Id, BaseClasses.AMMO_BOX)) + if (_itemHelper.IsOfBaseclass(itemTemplate.Id, [BaseClasses.AMMO_BOX])) { var boxAndCartridges = new List(); boxAndCartridges.Add(reward);