From 0b729fba119da217f4ed61784f3134eabf9d7ab2 Mon Sep 17 00:00:00 2001 From: Dev Date: Thu, 17 Oct 2024 13:05:01 +0100 Subject: [PATCH] Improvements to how weather temperature is calculated - takes into account current season Centralised the season override into `getActiveWeatherSeason()` Adjusted weather values based on client data --- project/assets/configs/weather.json | 36 ++++++++++++++----- project/src/controllers/WeatherController.ts | 7 ++-- project/src/generators/WeatherGenerator.ts | 18 ++++++---- .../src/models/spt/config/IWeatherConfig.ts | 2 +- project/src/services/RaidWeatherService.ts | 31 +++++++++++----- project/src/services/SeasonalEventService.ts | 4 +++ 6 files changed, 68 insertions(+), 30 deletions(-) diff --git a/project/assets/configs/weather.json b/project/assets/configs/weather.json index c9598672..cdcd957a 100644 --- a/project/assets/configs/weather.json +++ b/project/assets/configs/weather.json @@ -3,12 +3,12 @@ "weather": { "generateWeatherAmountHours": 24, "clouds": { - "values": [-1.5, -1, 0, 0.5, 1, 1.5], - "weights": [60, 50, 15, 5, 4, 3] + "values": [-1, 0, 0.5, 1, 1.5], + "weights": [100, 15, 5, 4, 3] }, "windSpeed": { - "values": [0, 1, 2, 3], - "weights": [4, 3, 2, 1] + "values": [0, 1, 2, 3, 4], + "weights": [6, 3, 2, 1, 1] }, "windDirection": { "values": [1, 2, 3, 4, 5, 6, 7, 8], @@ -19,8 +19,8 @@ "max": 1 }, "rain": { - "values": [1, 2, 3], - "weights": [25, 1, 1] + "values": [1, 2, 3, 4, 5], + "weights": [25, 1, 1, 1, 1] }, "rainIntensity": { "min": 0, @@ -31,12 +31,30 @@ "weights": [25, 8, 5, 5, 1] }, "temp": { - "min": 0, - "max": 24 + "0": { + "min": 17, + "max": 32 + }, + "1": { + "min": 7, + "max": 15 + }, + "2": { + "min": -10, + "max": 5 + }, + "3": { + "min": 1, + "max": 15 + }, + "4": { + "min": 0, + "max": 24 + } }, "pressure": { "min": 760, - "max": 764 + "max": 780 }, "timePeriod": { "values": [15, 30], diff --git a/project/src/controllers/WeatherController.ts b/project/src/controllers/WeatherController.ts index 629e0e13..40993ed2 100644 --- a/project/src/controllers/WeatherController.ts +++ b/project/src/controllers/WeatherController.ts @@ -30,7 +30,7 @@ export class WeatherController { let result: IWeatherData = { acceleration: 0, time: "", date: "", weather: undefined, season: 1 }; // defaults, hydrated below result = this.weatherGenerator.calculateGameTime(result); - result.weather = this.weatherGenerator.generateWeather(); + result.weather = this.weatherGenerator.generateWeather(result.season); return result; } @@ -46,10 +46,7 @@ export class WeatherController { /** Handle client/localGame/weather */ public generateLocal(sesssionId: string): IGetLocalWeatherResponseData { const result: IGetLocalWeatherResponseData = { - season: - this.weatherConfig.overrideSeason !== null - ? this.weatherConfig.overrideSeason - : this.seasonalEventService.getActiveWeatherSeason(), + season: this.seasonalEventService.getActiveWeatherSeason(), weather: [], }; diff --git a/project/src/generators/WeatherGenerator.ts b/project/src/generators/WeatherGenerator.ts index 3cff7f91..a4d61904 100644 --- a/project/src/generators/WeatherGenerator.ts +++ b/project/src/generators/WeatherGenerator.ts @@ -3,6 +3,7 @@ import { WeatherHelper } from "@spt/helpers/WeatherHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { IWeather, IWeatherData } from "@spt/models/eft/weather/IWeatherData"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; +import { Season } from "@spt/models/enums/Season"; import { WindDirection } from "@spt/models/enums/WindDirection"; import { IWeatherConfig } from "@spt/models/spt/config/IWeatherConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; @@ -46,10 +47,7 @@ export class WeatherGenerator { data.time = this.getBsgFormattedInRaidTime(); data.acceleration = this.weatherConfig.acceleration; - data.season = - this.weatherConfig.overrideSeason !== null - ? this.weatherConfig.overrideSeason - : this.seasonalEventService.getActiveWeatherSeason(); + data.season = this.seasonalEventService.getActiveWeatherSeason(); return data; } @@ -79,7 +77,7 @@ export class WeatherGenerator { * Return randomised Weather data with help of config/weather.json * @returns Randomised weather data */ - public generateWeather(timestamp?: number): IWeather { + public generateWeather(currentSeason: Season, timestamp?: number): IWeather { const clouds = this.getWeightedClouds(); // Force rain to off if no clouds @@ -93,7 +91,7 @@ export class WeatherGenerator { rain: rain, rain_intensity: rain > 1 ? this.getRandomFloat("rainIntensity") : 0, fog: this.getWeightedFog(), - temp: this.getRandomFloat("temp"), // TODO - lower value at night / take into account season + temp: 0, // TODO - lower value at night / take into account season pressure: this.getRandomFloat("pressure"), time: "", date: "", @@ -102,9 +100,17 @@ export class WeatherGenerator { this.setCurrentDateTime(result, timestamp); + result.temp = this.getRaidTemperature(currentSeason, result.time); + return result; } + protected getRaidTemperature(currentSeason: Season, currentTimeBsgFormatted: string): number { + // TODO, take into account time of day + const minMax = this.weatherConfig.weather.temp[currentSeason]; + return Number.parseFloat(this.randomUtil.getFloat(minMax.min, minMax.max).toPrecision(2)); + } + /** * Set IWeather date/time/timestamp values to now * @param weather Object to update diff --git a/project/src/models/spt/config/IWeatherConfig.ts b/project/src/models/spt/config/IWeatherConfig.ts index c427c0aa..6dd54af6 100644 --- a/project/src/models/spt/config/IWeatherConfig.ts +++ b/project/src/models/spt/config/IWeatherConfig.ts @@ -30,7 +30,7 @@ export interface IWeatherValues { rain: WeatherSettings; rainIntensity: MinMax; fog: WeatherSettings; - temp: MinMax; + temp: Record; pressure: MinMax; /** Length of each weather period */ timePeriod: WeatherSettings; diff --git a/project/src/services/RaidWeatherService.ts b/project/src/services/RaidWeatherService.ts index 54f1acd7..2efacb68 100644 --- a/project/src/services/RaidWeatherService.ts +++ b/project/src/services/RaidWeatherService.ts @@ -2,10 +2,12 @@ import { WeatherGenerator } from "@spt/generators/WeatherGenerator"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { IWeather } from "@spt/models/eft/weather/IWeatherData"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; +import { Season } from "@spt/models/enums/Season"; import { IWeatherConfig } from "@spt/models/spt/config/IWeatherConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; +import { SeasonalEventService } from "@spt/services/SeasonalEventService"; import { TimeUtil } from "@spt/utils/TimeUtil"; import { inject, injectable } from "tsyringe"; @@ -19,18 +21,20 @@ export class RaidWeatherService { @inject("DatabaseService") protected databaseService: DatabaseService, @inject("TimeUtil") protected timeUtil: TimeUtil, @inject("WeatherGenerator") protected weatherGenerator: WeatherGenerator, + @inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService, @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, @inject("ConfigServer") protected configServer: ConfigServer, ) { this.weatherConfig = this.configServer.getConfig(ConfigTypes.WEATHER); - this.generateWeather(); + const currentSeason = this.seasonalEventService.getActiveWeatherSeason(); + this.generateWeather(currentSeason); } /** * Generate 24 hours of weather data starting from midnight today */ - public generateWeather() { + public generateWeather(currentSeason: Season) { // When to start generating weather from in milliseconds const staringTimestampMs = this.timeUtil.getTodaysMidnightTimestamp(); @@ -42,13 +46,20 @@ export class RaidWeatherService { // Keep adding new weather until we have reached desired future date let nextTimestampMs = staringTimestampMs; while (nextTimestampMs <= futureTimestampToReachMs) { - const newWeather = this.weatherGenerator.generateWeather(nextTimestampMs); - this.logger.warning(`Handling ${new Date(nextTimestampMs)}`); - this.weatherForecast.push(newWeather); + const newWeatherToAddToCache = this.weatherGenerator.generateWeather(currentSeason, nextTimestampMs); + + // Add generated weather for time period to cache + this.weatherForecast.push(newWeatherToAddToCache); + + // Increment timestamp so next loop can begin at correct time nextTimestampMs += this.getWeightedWeatherTimePeriodMs(); } } + /** + * Get a time period to increment by, e.g 15 or 30 minutes as milliseconds + * @returns milliseconds + */ protected getWeightedWeatherTimePeriodMs(): number { const chosenTimePeriodMinutes = this.weightedRandomHelper.weightedRandom( this.weatherConfig.weather.timePeriod.values, @@ -62,7 +73,8 @@ export class RaidWeatherService { * Find the first matching weather object that applies to the current time */ public getCurrentWeather(): IWeather { - this.validateWeatherDataExists(); + const currentSeason = this.seasonalEventService.getActiveWeatherSeason(); + this.validateWeatherDataExists(currentSeason); return this.weatherForecast.find((x) => x.timestamp >= this.timeUtil.getTimestamp()); } @@ -71,7 +83,8 @@ export class RaidWeatherService { * Find the first matching weather object that applies to the current time + all following weather data generated */ public getUpcomingWeather(): IWeather[] { - this.validateWeatherDataExists(); + const currentSeason = this.seasonalEventService.getActiveWeatherSeason(); + this.validateWeatherDataExists(currentSeason); return this.weatherForecast.filter((x) => x.timestamp >= this.timeUtil.getTimestamp()); } @@ -79,7 +92,7 @@ export class RaidWeatherService { /** * Ensure future weather data exists */ - protected validateWeatherDataExists() { + protected validateWeatherDataExists(currentSeason: Season) { // Clear expired weather data this.weatherForecast = this.weatherForecast.filter((x) => x.timestamp < this.timeUtil.getTimestamp()); @@ -87,7 +100,7 @@ export class RaidWeatherService { const result = this.weatherForecast.filter((x) => x.timestamp >= this.timeUtil.getTimestamp()); if (result.length === 0) { // TODO - replace with better check, if < 1 hours worth of data exists? - this.generateWeather(); + this.generateWeather(currentSeason); } } } diff --git a/project/src/services/SeasonalEventService.ts b/project/src/services/SeasonalEventService.ts index d3b5d9a5..e6bebb45 100644 --- a/project/src/services/SeasonalEventService.ts +++ b/project/src/services/SeasonalEventService.ts @@ -232,6 +232,10 @@ export class SeasonalEventService { } public getActiveWeatherSeason(): Season { + if (this.weatherConfig.overrideSeason !== null) { + return this.weatherConfig.overrideSeason; + } + const currentDate = new Date(); for (const seasonRange of this.weatherConfig.seasonDates) { // Figure out start and end dates to get range of season