mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Tune turbulence values. Modify the range of values used to choose a wind speed. Wind speed at high elevation IRL can range from 20 to 160 knots around the globe. You may see wind speed generated here up to 100+ knots, but generally around 40 or so. IRL wind speed appears to depend on the latitude of the sun, not in this implementation. Note increased wind speeds in the changelog. Limit wind speed to 97 knots. Made minor adjustments to wind speed calculation. Calculate turbulance. Turbulance is based off time of day, and day of year. Each theatre may adjust their turbulance parameters. Spell turbulence correctly.
183 lines
6.3 KiB
Python
183 lines
6.3 KiB
Python
from __future__ import annotations
|
|
|
|
import datetime
|
|
from collections.abc import Iterator
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
import yaml
|
|
from dcs.terrain import (
|
|
Caucasus,
|
|
Falklands,
|
|
MarianaIslands,
|
|
Nevada,
|
|
Normandy,
|
|
PersianGulf,
|
|
Syria,
|
|
TheChannel,
|
|
)
|
|
|
|
from .conflicttheater import ConflictTheater
|
|
from .daytimemap import DaytimeMap
|
|
from .landmap import load_landmap
|
|
from .seasonalconditions import Season, SeasonalConditions, WeatherTypeChances
|
|
|
|
ALL_TERRAINS = [
|
|
Caucasus(),
|
|
Falklands(),
|
|
PersianGulf(),
|
|
Normandy(),
|
|
MarianaIslands(),
|
|
Nevada(),
|
|
TheChannel(),
|
|
Syria(),
|
|
]
|
|
|
|
TERRAINS_BY_NAME = {t.name: t for t in ALL_TERRAINS}
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class SeasonData:
|
|
average_temperature: float | None
|
|
average_pressure: float | None
|
|
weather: WeatherTypeChances
|
|
|
|
@staticmethod
|
|
def from_yaml(data: dict[str, Any]) -> SeasonData:
|
|
return SeasonData(
|
|
data.get("average_temperature"),
|
|
data.get("average_pressure"),
|
|
WeatherTypeChances(
|
|
data["weather"]["thunderstorm"],
|
|
data["weather"]["raining"],
|
|
data["weather"]["cloudy"],
|
|
data["weather"]["clear"],
|
|
),
|
|
)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class TurbulenceData:
|
|
high_avg_yearly_turbulence_per_10cm: float | None
|
|
low_avg_yearly_turbulence_per_10cm: float | None
|
|
solar_noon_turbulence_per_10cm: float | None
|
|
midnight_turbulence_per_10cm: float | None
|
|
|
|
@staticmethod
|
|
def from_yaml(data: dict[str, Any]) -> TurbulenceData:
|
|
return TurbulenceData(
|
|
data.get("high_avg_yearly_turbulence_per_10cm"),
|
|
data.get("low_avg_yearly_turbulence_per_10cm"),
|
|
data.get("solar_noon_turbulence_per_10cm"),
|
|
data.get("midnight_turbulence_per_10cm"),
|
|
)
|
|
|
|
|
|
class TheaterLoader:
|
|
THEATER_RESOURCE_DIR = Path("resources/theaters")
|
|
|
|
def __init__(self, name: str) -> None:
|
|
self.name = name
|
|
self.descriptor_path = self.THEATER_RESOURCE_DIR / self.name / "info.yaml"
|
|
|
|
@classmethod
|
|
def each(cls) -> Iterator[ConflictTheater]:
|
|
for theater_dir in cls.THEATER_RESOURCE_DIR.iterdir():
|
|
yield TheaterLoader(theater_dir.name).load()
|
|
|
|
@property
|
|
def landmap_path(self) -> Path:
|
|
return self.descriptor_path.with_name("landmap.p")
|
|
|
|
@property
|
|
def menu_thumbnail_dcs_relative_path(self) -> Path:
|
|
with self.descriptor_path.open() as descriptor_file:
|
|
data = yaml.safe_load(descriptor_file)
|
|
name = data.get("pydcs_name", data["name"])
|
|
return Path("Mods/terrains") / name / "Theme/icon.png"
|
|
|
|
def load(self) -> ConflictTheater:
|
|
with self.descriptor_path.open() as descriptor_file:
|
|
data = yaml.safe_load(descriptor_file)
|
|
return ConflictTheater(
|
|
TERRAINS_BY_NAME[data.get("pydcs_name", data["name"])],
|
|
load_landmap(self.landmap_path),
|
|
datetime.timezone(datetime.timedelta(hours=data["timezone"])),
|
|
self._load_seasonal_conditions(data["climate"]),
|
|
self._load_daytime_map(data["daytime"]),
|
|
)
|
|
|
|
def _load_daytime_map(self, daytime_data: dict[str, list[int]]) -> DaytimeMap:
|
|
return DaytimeMap(
|
|
dawn=self._load_daytime_range(daytime_data["dawn"]),
|
|
day=self._load_daytime_range(daytime_data["day"]),
|
|
dusk=self._load_daytime_range(daytime_data["dusk"]),
|
|
night=self._load_daytime_range(daytime_data["night"]),
|
|
)
|
|
|
|
@staticmethod
|
|
def _load_daytime_range(
|
|
daytime_range: list[int],
|
|
) -> tuple[datetime.time, datetime.time]:
|
|
begin, end = daytime_range
|
|
return datetime.time(hour=begin), datetime.time(hour=end)
|
|
|
|
def _load_seasonal_conditions(
|
|
self, climate_data: dict[str, Any]
|
|
) -> SeasonalConditions:
|
|
winter = SeasonData.from_yaml(climate_data["seasons"]["winter"])
|
|
spring = SeasonData.from_yaml(climate_data["seasons"]["spring"])
|
|
summer = SeasonData.from_yaml(climate_data["seasons"]["summer"])
|
|
fall = SeasonData.from_yaml(climate_data["seasons"]["fall"])
|
|
turbulence = TurbulenceData.from_yaml(climate_data["turbulence"])
|
|
if summer.average_pressure is None:
|
|
raise RuntimeError(
|
|
f"{self.descriptor_path} does not define a summer average pressure"
|
|
)
|
|
if summer.average_temperature is None:
|
|
raise RuntimeError(
|
|
f"{self.descriptor_path} does not define a summer average temperature"
|
|
)
|
|
if winter.average_pressure is None:
|
|
raise RuntimeError(
|
|
f"{self.descriptor_path} does not define a winter average pressure"
|
|
)
|
|
if winter.average_temperature is None:
|
|
raise RuntimeError(
|
|
f"{self.descriptor_path} does not define a winter average temperature"
|
|
)
|
|
if turbulence.high_avg_yearly_turbulence_per_10cm is None:
|
|
raise RuntimeError(
|
|
f"{self.descriptor_path} does not define a yearly average high turbulence"
|
|
)
|
|
if turbulence.low_avg_yearly_turbulence_per_10cm is None:
|
|
raise RuntimeError(
|
|
f"{self.descriptor_path} does not define a yearly average low turbulence"
|
|
)
|
|
if turbulence.solar_noon_turbulence_per_10cm is None:
|
|
raise RuntimeError(
|
|
f"{self.descriptor_path} does not define a solar noon turbulence"
|
|
)
|
|
if turbulence.midnight_turbulence_per_10cm is None:
|
|
raise RuntimeError(
|
|
f"{self.descriptor_path} does not define a midnight turbulence"
|
|
)
|
|
return SeasonalConditions(
|
|
summer.average_pressure,
|
|
winter.average_pressure,
|
|
summer.average_temperature,
|
|
winter.average_temperature,
|
|
climate_data["day_night_temperature_difference"],
|
|
turbulence.high_avg_yearly_turbulence_per_10cm,
|
|
turbulence.low_avg_yearly_turbulence_per_10cm,
|
|
turbulence.solar_noon_turbulence_per_10cm,
|
|
turbulence.midnight_turbulence_per_10cm,
|
|
{
|
|
Season.Winter: winter.weather,
|
|
Season.Spring: spring.weather,
|
|
Season.Summer: summer.weather,
|
|
Season.Fall: fall.weather,
|
|
},
|
|
)
|