mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Seasonal weather types per theater.
Adjusts the weather conditions per theater and per season.
This commit is contained in:
parent
f5dea4935c
commit
4c51b4b822
@ -51,6 +51,7 @@ from .controlpoint import (
|
||||
MissionTarget,
|
||||
OffMapSpawn,
|
||||
)
|
||||
from .seasonalconditions import SeasonalConditions
|
||||
from .frontline import FrontLine
|
||||
from .landmap import Landmap, load_landmap, poly_contains
|
||||
from .latlon import LatLon
|
||||
@ -527,17 +528,6 @@ class ReferencePoint:
|
||||
image_coordinates: Point
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SeasonalConditions:
|
||||
# Units are inHg and degrees Celsius
|
||||
# Future improvement: add clouds/precipitation
|
||||
summer_avg_pressure: float
|
||||
winter_avg_pressure: float
|
||||
summer_avg_temperature: float
|
||||
winter_avg_temperature: float
|
||||
temperature_day_night_difference: float
|
||||
|
||||
|
||||
class ConflictTheater:
|
||||
terrain: Terrain
|
||||
|
||||
@ -799,13 +789,9 @@ class CaucasusTheater(ConflictTheater):
|
||||
|
||||
@property
|
||||
def seasonal_conditions(self) -> SeasonalConditions:
|
||||
return SeasonalConditions(
|
||||
summer_avg_pressure=30.02, # TODO: More science
|
||||
winter_avg_pressure=29.72, # TODO: More science
|
||||
summer_avg_temperature=22.5,
|
||||
winter_avg_temperature=3.0,
|
||||
temperature_day_night_difference=6.0,
|
||||
)
|
||||
from .seasonalconditions.caucasus import CONDITIONS
|
||||
|
||||
return CONDITIONS
|
||||
|
||||
@property
|
||||
def projection_parameters(self) -> TransverseMercator:
|
||||
@ -831,13 +817,9 @@ class PersianGulfTheater(ConflictTheater):
|
||||
|
||||
@property
|
||||
def seasonal_conditions(self) -> SeasonalConditions:
|
||||
return SeasonalConditions(
|
||||
summer_avg_pressure=29.98, # TODO: More science
|
||||
winter_avg_pressure=29.80, # TODO: More science
|
||||
summer_avg_temperature=32.5,
|
||||
winter_avg_temperature=15.0,
|
||||
temperature_day_night_difference=2.0,
|
||||
)
|
||||
from .seasonalconditions.persiangulf import CONDITIONS
|
||||
|
||||
return CONDITIONS
|
||||
|
||||
@property
|
||||
def projection_parameters(self) -> TransverseMercator:
|
||||
@ -863,13 +845,9 @@ class NevadaTheater(ConflictTheater):
|
||||
|
||||
@property
|
||||
def seasonal_conditions(self) -> SeasonalConditions:
|
||||
return SeasonalConditions(
|
||||
summer_avg_pressure=30.02, # TODO: More science
|
||||
winter_avg_pressure=29.72, # TODO: More science
|
||||
summer_avg_temperature=31.5,
|
||||
winter_avg_temperature=5.0,
|
||||
temperature_day_night_difference=6.0,
|
||||
)
|
||||
from .seasonalconditions.nevada import CONDITIONS
|
||||
|
||||
return CONDITIONS
|
||||
|
||||
@property
|
||||
def projection_parameters(self) -> TransverseMercator:
|
||||
@ -895,13 +873,9 @@ class NormandyTheater(ConflictTheater):
|
||||
|
||||
@property
|
||||
def seasonal_conditions(self) -> SeasonalConditions:
|
||||
return SeasonalConditions(
|
||||
summer_avg_pressure=30.02, # TODO: More science
|
||||
winter_avg_pressure=29.72, # TODO: More science
|
||||
summer_avg_temperature=20.0,
|
||||
winter_avg_temperature=0.0,
|
||||
temperature_day_night_difference=5.0,
|
||||
)
|
||||
from .seasonalconditions.normandy import CONDITIONS
|
||||
|
||||
return CONDITIONS
|
||||
|
||||
@property
|
||||
def projection_parameters(self) -> TransverseMercator:
|
||||
@ -927,13 +901,9 @@ class TheChannelTheater(ConflictTheater):
|
||||
|
||||
@property
|
||||
def seasonal_conditions(self) -> SeasonalConditions:
|
||||
return SeasonalConditions(
|
||||
summer_avg_pressure=30.02, # TODO: More science
|
||||
winter_avg_pressure=29.72, # TODO: More science
|
||||
summer_avg_temperature=20.0,
|
||||
winter_avg_temperature=0.0,
|
||||
temperature_day_night_difference=5.0,
|
||||
)
|
||||
from .seasonalconditions.thechannel import CONDITIONS
|
||||
|
||||
return CONDITIONS
|
||||
|
||||
@property
|
||||
def projection_parameters(self) -> TransverseMercator:
|
||||
@ -959,13 +929,9 @@ class SyriaTheater(ConflictTheater):
|
||||
|
||||
@property
|
||||
def seasonal_conditions(self) -> SeasonalConditions:
|
||||
return SeasonalConditions(
|
||||
summer_avg_pressure=29.98, # TODO: More science
|
||||
winter_avg_pressure=29.86, # TODO: More science
|
||||
summer_avg_temperature=28.5,
|
||||
winter_avg_temperature=10.0,
|
||||
temperature_day_night_difference=8.0,
|
||||
)
|
||||
from .seasonalconditions.syria import CONDITIONS
|
||||
|
||||
return CONDITIONS
|
||||
|
||||
@property
|
||||
def projection_parameters(self) -> TransverseMercator:
|
||||
@ -988,13 +954,9 @@ class MarianaIslandsTheater(ConflictTheater):
|
||||
|
||||
@property
|
||||
def seasonal_conditions(self) -> SeasonalConditions:
|
||||
return SeasonalConditions(
|
||||
summer_avg_pressure=30.02, # TODO: More science
|
||||
winter_avg_pressure=29.82, # TODO: More science
|
||||
summer_avg_temperature=28.0,
|
||||
winter_avg_temperature=27.0,
|
||||
temperature_day_night_difference=1.0,
|
||||
)
|
||||
from .seasonalconditions.marianaislands import CONDITIONS
|
||||
|
||||
return CONDITIONS
|
||||
|
||||
@property
|
||||
def projection_parameters(self) -> TransverseMercator:
|
||||
|
||||
1
game/theater/seasonalconditions/__init__.py
Normal file
1
game/theater/seasonalconditions/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .seasonalconditions import *
|
||||
36
game/theater/seasonalconditions/caucasus.py
Normal file
36
game/theater/seasonalconditions/caucasus.py
Normal file
@ -0,0 +1,36 @@
|
||||
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
|
||||
|
||||
CONDITIONS = SeasonalConditions(
|
||||
summer_avg_pressure=30.02, # TODO: Find real-world data
|
||||
winter_avg_pressure=29.72, # TODO: Find real-world data
|
||||
summer_avg_temperature=22.5,
|
||||
winter_avg_temperature=3.0,
|
||||
temperature_day_night_difference=6.0,
|
||||
weather_type_chances={
|
||||
# TODO: Find real-world data for all these values
|
||||
Season.Winter: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=20,
|
||||
cloudy=60,
|
||||
clear_skies=20,
|
||||
),
|
||||
Season.Spring: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=20,
|
||||
cloudy=40,
|
||||
clear_skies=40,
|
||||
),
|
||||
Season.Summer: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=10,
|
||||
cloudy=30,
|
||||
clear_skies=60,
|
||||
),
|
||||
Season.Fall: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=30,
|
||||
cloudy=50,
|
||||
clear_skies=20,
|
||||
),
|
||||
},
|
||||
)
|
||||
38
game/theater/seasonalconditions/marianaislands.py
Normal file
38
game/theater/seasonalconditions/marianaislands.py
Normal file
@ -0,0 +1,38 @@
|
||||
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
|
||||
|
||||
CONDITIONS = SeasonalConditions(
|
||||
summer_avg_pressure=30.02, # TODO: Find real-world data
|
||||
winter_avg_pressure=29.82, # TODO: Find real-world data
|
||||
summer_avg_temperature=28.0,
|
||||
winter_avg_temperature=27.0,
|
||||
temperature_day_night_difference=1.0,
|
||||
weather_type_chances={
|
||||
# TODO: Find real-world data for all these values
|
||||
Season.Winter: WeatherTypeChances(
|
||||
thunderstorm=2,
|
||||
raining=20,
|
||||
cloudy=40,
|
||||
clear_skies=40,
|
||||
),
|
||||
Season.Spring: WeatherTypeChances(
|
||||
# Spring is dry/sunny in Marianas
|
||||
thunderstorm=1,
|
||||
raining=10,
|
||||
cloudy=30,
|
||||
clear_skies=60,
|
||||
),
|
||||
Season.Summer: WeatherTypeChances(
|
||||
thunderstorm=2,
|
||||
raining=20,
|
||||
cloudy=40,
|
||||
clear_skies=40,
|
||||
),
|
||||
Season.Fall: WeatherTypeChances(
|
||||
# Rain season
|
||||
thunderstorm=5,
|
||||
raining=45,
|
||||
cloudy=30,
|
||||
clear_skies=20,
|
||||
),
|
||||
},
|
||||
)
|
||||
36
game/theater/seasonalconditions/nevada.py
Normal file
36
game/theater/seasonalconditions/nevada.py
Normal file
@ -0,0 +1,36 @@
|
||||
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
|
||||
|
||||
CONDITIONS = SeasonalConditions(
|
||||
summer_avg_pressure=30.02, # TODO: Find real-world data
|
||||
winter_avg_pressure=29.72, # TODO: Find real-world data
|
||||
summer_avg_temperature=31.5,
|
||||
winter_avg_temperature=5.0,
|
||||
temperature_day_night_difference=6.0,
|
||||
weather_type_chances={
|
||||
# TODO: Find real-world data for all these values
|
||||
Season.Winter: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=10,
|
||||
cloudy=50,
|
||||
clear_skies=40,
|
||||
),
|
||||
Season.Spring: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=5,
|
||||
cloudy=45,
|
||||
clear_skies=50,
|
||||
),
|
||||
Season.Summer: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=5,
|
||||
cloudy=25,
|
||||
clear_skies=70,
|
||||
),
|
||||
Season.Fall: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=10,
|
||||
cloudy=45,
|
||||
clear_skies=45,
|
||||
),
|
||||
},
|
||||
)
|
||||
36
game/theater/seasonalconditions/normandy.py
Normal file
36
game/theater/seasonalconditions/normandy.py
Normal file
@ -0,0 +1,36 @@
|
||||
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
|
||||
|
||||
CONDITIONS = SeasonalConditions(
|
||||
summer_avg_pressure=30.02, # TODO: Find real-world data
|
||||
winter_avg_pressure=29.72, # TODO: Find real-world data
|
||||
summer_avg_temperature=20.0,
|
||||
winter_avg_temperature=0.0,
|
||||
temperature_day_night_difference=5.0,
|
||||
weather_type_chances={
|
||||
# TODO: Find real-world data for all these values
|
||||
Season.Winter: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=20,
|
||||
cloudy=60,
|
||||
clear_skies=20,
|
||||
),
|
||||
Season.Spring: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=20,
|
||||
cloudy=40,
|
||||
clear_skies=40,
|
||||
),
|
||||
Season.Summer: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=10,
|
||||
cloudy=30,
|
||||
clear_skies=60,
|
||||
),
|
||||
Season.Fall: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=30,
|
||||
cloudy=50,
|
||||
clear_skies=20,
|
||||
),
|
||||
},
|
||||
)
|
||||
37
game/theater/seasonalconditions/persiangulf.py
Normal file
37
game/theater/seasonalconditions/persiangulf.py
Normal file
@ -0,0 +1,37 @@
|
||||
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
|
||||
|
||||
CONDITIONS = SeasonalConditions(
|
||||
summer_avg_pressure=29.98, # TODO: Find real-world data
|
||||
winter_avg_pressure=29.80, # TODO: Find real-world data
|
||||
summer_avg_temperature=32.5,
|
||||
winter_avg_temperature=15.0,
|
||||
temperature_day_night_difference=2.0,
|
||||
weather_type_chances={
|
||||
# TODO: Find real-world data for all these values
|
||||
Season.Winter: WeatherTypeChances(
|
||||
# Winter there is some rain in PG (Dubai)
|
||||
thunderstorm=1,
|
||||
raining=15,
|
||||
cloudy=35,
|
||||
clear_skies=50,
|
||||
),
|
||||
Season.Spring: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=2,
|
||||
cloudy=18,
|
||||
clear_skies=80,
|
||||
),
|
||||
Season.Summer: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=1,
|
||||
cloudy=8,
|
||||
clear_skies=90,
|
||||
),
|
||||
Season.Fall: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=2,
|
||||
cloudy=18,
|
||||
clear_skies=80,
|
||||
),
|
||||
},
|
||||
)
|
||||
48
game/theater/seasonalconditions/seasonalconditions.py
Normal file
48
game/theater/seasonalconditions/seasonalconditions.py
Normal file
@ -0,0 +1,48 @@
|
||||
import datetime
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class Season(Enum):
|
||||
Winter = "winter"
|
||||
Spring = "spring"
|
||||
Summer = "summer"
|
||||
Fall = "fall"
|
||||
|
||||
|
||||
def determine_season(day: datetime.date) -> Season:
|
||||
# Note: This logic doesn't need to be very precise
|
||||
# Currently refers strictly to northern-hemisphere seasons
|
||||
day_of_year = day.timetuple().tm_yday
|
||||
season_length = 365.0 / 4
|
||||
winter_end_day = season_length / 2
|
||||
if day_of_year < winter_end_day:
|
||||
return Season.Winter
|
||||
elif day_of_year < winter_end_day + season_length:
|
||||
return Season.Spring
|
||||
elif day_of_year < winter_end_day + season_length * 2:
|
||||
return Season.Summer
|
||||
elif day_of_year < winter_end_day + season_length * 3:
|
||||
return Season.Fall
|
||||
else:
|
||||
return Season.Winter
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class WeatherTypeChances:
|
||||
thunderstorm: float
|
||||
raining: float
|
||||
cloudy: float
|
||||
clear_skies: float
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SeasonalConditions:
|
||||
# Units are inHg and degrees Celsius
|
||||
summer_avg_pressure: float
|
||||
winter_avg_pressure: float
|
||||
summer_avg_temperature: float
|
||||
winter_avg_temperature: float
|
||||
temperature_day_night_difference: float
|
||||
|
||||
weather_type_chances: dict[Season, WeatherTypeChances]
|
||||
36
game/theater/seasonalconditions/syria.py
Normal file
36
game/theater/seasonalconditions/syria.py
Normal file
@ -0,0 +1,36 @@
|
||||
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
|
||||
|
||||
CONDITIONS = SeasonalConditions(
|
||||
summer_avg_pressure=29.98, # TODO: Find real-world data
|
||||
winter_avg_pressure=29.86, # TODO: Find real-world data
|
||||
summer_avg_temperature=28.5,
|
||||
winter_avg_temperature=10.0,
|
||||
temperature_day_night_difference=8.0,
|
||||
weather_type_chances={
|
||||
# TODO: Find real-world data for all these values
|
||||
Season.Winter: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=25,
|
||||
cloudy=25,
|
||||
clear_skies=50,
|
||||
),
|
||||
Season.Spring: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=10,
|
||||
cloudy=30,
|
||||
clear_skies=60,
|
||||
),
|
||||
Season.Summer: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=3,
|
||||
cloudy=20,
|
||||
clear_skies=77,
|
||||
),
|
||||
Season.Fall: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=10,
|
||||
cloudy=30,
|
||||
clear_skies=60,
|
||||
),
|
||||
},
|
||||
)
|
||||
36
game/theater/seasonalconditions/thechannel.py
Normal file
36
game/theater/seasonalconditions/thechannel.py
Normal file
@ -0,0 +1,36 @@
|
||||
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
|
||||
|
||||
CONDITIONS = SeasonalConditions(
|
||||
summer_avg_pressure=30.02, # TODO: Find real-world data
|
||||
winter_avg_pressure=29.72, # TODO: Find real-world data
|
||||
summer_avg_temperature=20.0,
|
||||
winter_avg_temperature=0.0,
|
||||
temperature_day_night_difference=5.0,
|
||||
weather_type_chances={
|
||||
# TODO: Find real-world data for all these values
|
||||
Season.Winter: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=20,
|
||||
cloudy=60,
|
||||
clear_skies=20,
|
||||
),
|
||||
Season.Spring: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=20,
|
||||
cloudy=40,
|
||||
clear_skies=40,
|
||||
),
|
||||
Season.Summer: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=10,
|
||||
cloudy=30,
|
||||
clear_skies=60,
|
||||
),
|
||||
Season.Fall: WeatherTypeChances(
|
||||
thunderstorm=1,
|
||||
raining=30,
|
||||
cloudy=50,
|
||||
clear_skies=20,
|
||||
),
|
||||
},
|
||||
)
|
||||
@ -14,9 +14,11 @@ from game.savecompat import has_save_compat_for
|
||||
from game.settings import Settings
|
||||
from game.utils import Distance, Heading, meters, interpolate, Pressure, inches_hg
|
||||
|
||||
from game.theater.seasonalconditions import determine_season
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game.theater import ConflictTheater
|
||||
from game.theater.conflicttheater import SeasonalConditions
|
||||
from game.theater.seasonalconditions import SeasonalConditions
|
||||
|
||||
|
||||
class TimeOfDay(Enum):
|
||||
@ -119,10 +121,18 @@ class Weather:
|
||||
temperature -= seasonal_conditions.temperature_day_night_difference / 2
|
||||
pressure += self.pressure_adjustment
|
||||
temperature += self.temperature_adjustment
|
||||
logging.debug(
|
||||
"Weather: Before random: temp {} press {}".format(temperature, pressure)
|
||||
)
|
||||
conditions = AtmosphericConditions(
|
||||
qnh=self.random_pressure(pressure),
|
||||
temperature_celsius=self.random_temperature(temperature),
|
||||
)
|
||||
logging.debug(
|
||||
"Weather: After random: temp {} press {}".format(
|
||||
conditions.temperature_celsius, conditions.qnh.pressure_in_inches_hg
|
||||
)
|
||||
)
|
||||
return conditions
|
||||
|
||||
@property
|
||||
@ -334,14 +344,18 @@ class Conditions:
|
||||
day: datetime.date,
|
||||
time_of_day: TimeOfDay,
|
||||
) -> Weather:
|
||||
# Future improvement: use seasonal weights for theaters
|
||||
season = determine_season(day)
|
||||
logging.debug("Weather: Season {}".format(season))
|
||||
weather_chances = seasonal_conditions.weather_type_chances[season]
|
||||
chances = {
|
||||
Thunderstorm: 1,
|
||||
Raining: 20,
|
||||
Cloudy: 60,
|
||||
ClearSkies: 20,
|
||||
Thunderstorm: weather_chances.thunderstorm,
|
||||
Raining: weather_chances.raining,
|
||||
Cloudy: weather_chances.cloudy,
|
||||
ClearSkies: weather_chances.clear_skies,
|
||||
}
|
||||
logging.debug("Weather: Chances {}".format(weather_chances))
|
||||
weather_type = random.choices(
|
||||
list(chances.keys()), weights=list(chances.values())
|
||||
)[0]
|
||||
logging.debug("Weather: Type {}".format(weather_type))
|
||||
return weather_type(seasonal_conditions, day, time_of_day)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user