Merge branch 'main' of https://github.com/sp-tarkov/server-csharp
This commit is contained in:
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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<WeatherConfig>(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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1044,9 +1044,9 @@ public class ItemHelper
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsOfBaseclass(string valueEncyclopedia, string weapon)
|
||||
public bool IsOfBaseclass(string tpl, List<string> baseClassTpls)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _itemBaseClassService.ItemHasBaseClass(tpl, baseClassTpls);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
return new DateTime().AddMilliseconds(
|
||||
(russiaOffsetMilliseconds + russiaOffsetMilliseconds * _weatherConfig.Acceleration) %
|
||||
twentyFourHoursMilliseconds);
|
||||
return _timeUtil.GetDateTimeFromTimeStamp((long)
|
||||
(russiaOffsetMilliseconds + currentTimestampMilliSeconds * _weatherConfig.Acceleration) %
|
||||
twentyFourHoursMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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<Item>();
|
||||
boxAndCartridges.Add(reward);
|
||||
|
||||
@@ -184,4 +184,16 @@ public class TimeUtil
|
||||
{
|
||||
return DateTimeOffset.FromUnixTimeMilliseconds(timeStamp).DateTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes a timestamp and gets difference between Epoch time and time provided resulting in a unixtimestamp (date defaults to utcnow)
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public long GetTimeStampFromEpoch(DateTime? date = null)
|
||||
{
|
||||
var dateToCompare = date ?? DateTime.UtcNow;
|
||||
return (long)(dateToCompare - DateTime.UnixEpoch).TotalSeconds;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user