using System; using Dalamud.Plugin.Services; using Lumina.Excel; using Lumina.Excel.Sheets; namespace LLib.GameData; public sealed class WeatherHelper { public const double WeatherPeriodSeconds = 1400.0; private readonly IDataManager _dataManager; public WeatherHelper(IDataManager dataManager) { _dataManager = dataManager; } public Weather? GetCurrentWeather(uint territoryId) { return GetWeatherAtTime(territoryId, DateTimeOffset.UtcNow.ToUnixTimeSeconds()); } public Weather? GetPreviousWeather(uint territoryId) { return GetWeatherAtTime(territoryId, DateTimeOffset.UtcNow.ToUnixTimeSeconds() - 1400); } public Weather? GetNextWeather(uint territoryId) { return GetWeatherAtTime(territoryId, DateTimeOffset.UtcNow.ToUnixTimeSeconds() + 1400); } public static double GetSecondsUntilWeatherChange() { long num = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); return 1400.0 - (double)(num % 1400); } public Weather? GetWeatherAtTime(uint territoryId, long unixSeconds) { TerritoryType? rowOrDefault = _dataManager.GetExcelSheet().GetRowOrDefault(territoryId); if (!rowOrDefault.HasValue) { return null; } if (!rowOrDefault.Value.WeatherRate.IsValid) { return null; } WeatherRate value = rowOrDefault.Value.WeatherRate.Value; uint target = CalculateTarget(unixSeconds); return ResolveWeather(value, target); } internal static uint CalculateTarget(long unixSeconds) { long num = unixSeconds / 175; uint num2 = (uint)((num + 8 - num % 8) % 24); uint num3 = (uint)((int)(unixSeconds / 4200) * 100) + num2; uint num4 = (num3 << 11) ^ num3; return ((num4 >> 8) ^ num4) % 100; } private static Weather? ResolveWeather(WeatherRate weatherRate, uint target) { Weather? result = null; int num = 0; for (int i = 0; i < weatherRate.Rate.Count; i++) { if (weatherRate.Rate[i] <= 0) { continue; } RowRef rowRef = weatherRate.Weather[i]; if (rowRef.IsValid) { result = rowRef.Value; } num += weatherRate.Rate[i]; if (target < num) { if (!rowRef.IsValid) { return null; } return rowRef.Value; } } return result; } }