mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Use weibull distribution for wind generation.
Wind speeds should not be uniformly distributed. This switches to a Weibull distribution which allegedly (see the bug) is good enough. Experimentally that seems true as well, though I know nothing about how wind works irl. This at least looks like it'll generate reasonable variation in missions while keeping the 1st through 3rd quartile behaviors from getting out of hand. I'm very uncertain about the scaling factor aspect of this. Naively the wind speeds at different altitudes ought to be somewhat correlated, but I'm not sure how much, and whether this kind of scaling is at all the right way to do it. As before, meh, close enough? Fixes https://github.com/dcs-liberation/dcs_liberation/issues/2861.
This commit is contained in:
parent
b750099b16
commit
73e0cbe182
@ -134,7 +134,8 @@ Saves from 6.x are not compatible with 7.0.
|
|||||||
* **[Flight Planning]** Package TOT and composition can be modified after advancing time in Liberation.
|
* **[Flight Planning]** Package TOT and composition can be modified after advancing time in Liberation.
|
||||||
* **[Mission Generation]** Units on the front line are now hidden on MFDs.
|
* **[Mission Generation]** Units on the front line are now hidden on MFDs.
|
||||||
* **[Mission Generation]** Preset radio channels will now be configured for both A-10C modules.
|
* **[Mission Generation]** Preset radio channels will now be configured for both A-10C modules.
|
||||||
* **[Mission Generation]** Both A-10C modules now use separate radios for inter- and intra-flight comms (similar to other modern aircraft).
|
* **[Mission Generation]** The A-10C II now uses separate radios for inter- and intra-flight comms (similar to other modern aircraft).
|
||||||
|
* **[Mission Generation]** Wind speeds no longer follow a uniform distribution. Median wind speeds are now much lower and the standard deviation has been reduced considerably at altitude but increased somewhat at MSL.
|
||||||
* **[Modding]** Updated Community A-4E-C mod version support to 2.1.0 release.
|
* **[Modding]** Updated Community A-4E-C mod version support to 2.1.0 release.
|
||||||
* **[Modding]** Add support for VSN F-4B and F-4C mod.
|
* **[Modding]** Add support for VSN F-4B and F-4C mod.
|
||||||
* **[Modding]** Aircraft task capabilities and preferred aircraft for each task are now moddable in the aircraft unit yaml files. Each aircraft has a weight per task. Higher weights are given higher preference.
|
* **[Modding]** Aircraft task capabilities and preferred aircraft for each task are now moddable in the aircraft unit yaml files. Each aircraft has a weight per task. Higher weights are given higher preference.
|
||||||
|
|||||||
@ -21,6 +21,7 @@ from game.utils import (
|
|||||||
interpolate,
|
interpolate,
|
||||||
knots,
|
knots,
|
||||||
meters,
|
meters,
|
||||||
|
Speed,
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -185,56 +186,39 @@ class Weather:
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def random_wind(minimum: int, maximum: int) -> WindConditions:
|
def random_wind(
|
||||||
|
weibull_shape: float,
|
||||||
|
weibull_scale_speed: Speed,
|
||||||
|
at_2000m_factor_range: tuple[float, float],
|
||||||
|
at_8000m_factor_range: tuple[float, float],
|
||||||
|
) -> WindConditions:
|
||||||
|
"""Generates random wind."""
|
||||||
wind_direction = Heading.random()
|
wind_direction = Heading.random()
|
||||||
wind_direction_2000m = wind_direction + Heading.random(-90, 90)
|
wind_direction_2000m = wind_direction + Heading.random(-90, 90)
|
||||||
wind_direction_8000m = wind_direction + Heading.random(-90, 90)
|
wind_direction_8000m = wind_direction + Heading.random(-90, 90)
|
||||||
at_0m_factor = 1
|
|
||||||
at_2000m_factor = 3 + random.choice([0, 0, 0, 0, 0, 1, 1])
|
|
||||||
|
|
||||||
high_alt_variation = random.choice(
|
# The first parameter is the scale. 63.2% of all results will fall below that
|
||||||
[
|
# value.
|
||||||
-3,
|
# https://www.itl.nist.gov/div898/handbook/eda/section3/weibplot.htm
|
||||||
-3,
|
msl = random.weibullvariate(
|
||||||
-2,
|
weibull_scale_speed.meters_per_second, weibull_shape
|
||||||
-2,
|
|
||||||
-2,
|
|
||||||
-2,
|
|
||||||
-2,
|
|
||||||
-2,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
at_8000m_factor = at_2000m_factor + 5 + high_alt_variation
|
at_2000m_factor = random.uniform(*at_2000m_factor_range)
|
||||||
|
at_8000m_factor = random.uniform(*at_8000m_factor_range)
|
||||||
base_wind = random.randint(minimum, maximum)
|
|
||||||
|
|
||||||
# DCS is limited to 97 knots wind speed.
|
# DCS is limited to 97 knots wind speed.
|
||||||
max_supported_wind_speed = knots(97).meters_per_second
|
max_supported_wind_speed = knots(97).meters_per_second
|
||||||
|
|
||||||
return WindConditions(
|
return WindConditions(
|
||||||
# Always some wind to make the smoke move a bit.
|
# Always some wind to make the smoke move a bit.
|
||||||
at_0m=Wind(wind_direction.degrees, max(1, base_wind * at_0m_factor)),
|
at_0m=Wind(wind_direction.degrees, max(1.0, msl)),
|
||||||
at_2000m=Wind(
|
at_2000m=Wind(
|
||||||
wind_direction_2000m.degrees,
|
wind_direction_2000m.degrees,
|
||||||
min(max_supported_wind_speed, base_wind * at_2000m_factor),
|
min(max_supported_wind_speed, msl * at_2000m_factor),
|
||||||
),
|
),
|
||||||
at_8000m=Wind(
|
at_8000m=Wind(
|
||||||
wind_direction_8000m.degrees,
|
wind_direction_8000m.degrees,
|
||||||
min(max_supported_wind_speed, base_wind * at_8000m_factor),
|
min(max_supported_wind_speed, msl * at_8000m_factor),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -334,7 +318,7 @@ class ClearSkies(Weather):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def generate_wind(self) -> WindConditions:
|
def generate_wind(self) -> WindConditions:
|
||||||
return self.random_wind(1, 4)
|
return self.random_wind(1.5, knots(5), (1, 1.8), (1.5, 2.5))
|
||||||
|
|
||||||
|
|
||||||
class Cloudy(Weather):
|
class Cloudy(Weather):
|
||||||
@ -358,7 +342,7 @@ class Cloudy(Weather):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def generate_wind(self) -> WindConditions:
|
def generate_wind(self) -> WindConditions:
|
||||||
return self.random_wind(1, 5)
|
return self.random_wind(1.6, knots(6.5), (1, 1.8), (1.5, 2.5))
|
||||||
|
|
||||||
|
|
||||||
class Raining(Weather):
|
class Raining(Weather):
|
||||||
@ -382,7 +366,7 @@ class Raining(Weather):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def generate_wind(self) -> WindConditions:
|
def generate_wind(self) -> WindConditions:
|
||||||
return self.random_wind(2, 6)
|
return self.random_wind(2.6, knots(12), (1, 1.7), (2.2, 2.8))
|
||||||
|
|
||||||
|
|
||||||
class Thunderstorm(Weather):
|
class Thunderstorm(Weather):
|
||||||
@ -407,7 +391,7 @@ class Thunderstorm(Weather):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def generate_wind(self) -> WindConditions:
|
def generate_wind(self) -> WindConditions:
|
||||||
return self.random_wind(2, 8)
|
return self.random_wind(6, knots(20), (1, 2), (2.5, 3.5))
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user