diff --git a/game/dcs/aircrafttype.py b/game/dcs/aircrafttype.py index 4b581d42..383ff385 100644 --- a/game/dcs/aircrafttype.py +++ b/game/dcs/aircrafttype.py @@ -154,6 +154,9 @@ class AircraftType(UnitType[Type[FlyingType]]): # main weapon. It'll RTB when it doesn't have gun ammo left. gunfighter: bool + # If true, kneeboards will be generated in metric units + metric_kneeboard: bool + max_group_size: int patrol_altitude: Optional[Distance] patrol_speed: Optional[Speed] @@ -395,4 +398,5 @@ class AircraftType(UnitType[Type[FlyingType]]): intra_flight_radio=radio_config.intra_flight, channel_allocator=radio_config.channel_allocator, channel_namer=radio_config.channel_namer, + metric_kneeboard=data.get("metric_kneeboard", False), ) diff --git a/game/missiongenerator/kneeboard.py b/game/missiongenerator/kneeboard.py index e4d47a06..6a1900fc 100644 --- a/game/missiongenerator/kneeboard.py +++ b/game/missiongenerator/kneeboard.py @@ -44,7 +44,7 @@ from game.dcs.aircrafttype import AircraftType from game.radio.radios import RadioFrequency from game.theater import ConflictTheater, LatLon, TheaterGroundObject from game.theater.bullseye import Bullseye -from game.utils import meters +from game.utils import Distance, meters from game.weather import Weather from gen.runways import RunwayData from .aircraft.flightdata import FlightData @@ -202,11 +202,12 @@ class FlightPlanBuilder: WAYPOINT_DESC_MAX_LEN = 25 - def __init__(self, start_time: datetime.datetime) -> None: + def __init__(self, start_time: datetime.datetime, is_metric: bool) -> None: self.start_time = start_time self.rows: List[List[str]] = [] self.target_points: List[NumberedWaypoint] = [] self.last_waypoint: Optional[FlightWaypoint] = None + self.is_metric = is_metric def add_waypoint(self, waypoint_num: int, waypoint: FlightWaypoint) -> None: if waypoint.waypoint_type == FlightWaypointType.TARGET_POINT: @@ -251,8 +252,9 @@ class FlightPlanBuilder: waypoint.waypoint.pretty_name, FlightPlanBuilder.WAYPOINT_DESC_MAX_LEN, ), - str(int(waypoint.waypoint.alt.feet)), + self._format_alt(waypoint.waypoint.alt), self._waypoint_distance(waypoint.waypoint), + self._waypoint_bearing(waypoint.waypoint), self._ground_speed(waypoint.waypoint), self._format_time(waypoint.waypoint.tot), self._format_time(waypoint.waypoint.departure_time), @@ -266,14 +268,33 @@ class FlightPlanBuilder: local_time = self.start_time + time return local_time.strftime(f"%H:%M:%S") + def _format_alt(self, alt: Distance) -> str: + if self.is_metric: + return f"{alt.meters:.0f} m" + else: + return f"{alt.feet:.0f} ft" + def _waypoint_distance(self, waypoint: FlightWaypoint) -> str: if self.last_waypoint is None: return "-" - distance = meters( - self.last_waypoint.position.distance_to_point(waypoint.position) - ) - return f"{distance.nautical_miles:.1f} NM" + if self.is_metric: + distance = meters( + self.last_waypoint.position.distance_to_point(waypoint.position) + ) + return f"{(distance.meters / 1000):.1f} km" + else: + distance = meters( + self.last_waypoint.position.distance_to_point(waypoint.position) + ) + return f"{distance.nautical_miles:.1f} nm" + + def _waypoint_bearing(self, waypoint: FlightWaypoint) -> str: + if self.last_waypoint is None: + return "-" + bearing = self.last_waypoint.position.heading_between_point(waypoint.position) + + return f"{(bearing):.0f} T" def _ground_speed(self, waypoint: FlightWaypoint) -> str: if self.last_waypoint is None: @@ -293,7 +314,10 @@ class FlightPlanBuilder: self.last_waypoint.position.distance_to_point(waypoint.position) ) duration = (waypoint.tot - last_time).total_seconds() / 3600 - return f"{int(distance.nautical_miles / duration)} kt" + if self.is_metric: + return f"{int((distance.meters / 1000) / duration)} km/h" + else: + return f"{int(distance.nautical_miles / duration)} kt" @staticmethod def _format_min_fuel(min_fuel: Optional[float]) -> str: @@ -349,7 +373,9 @@ class BriefingPage(KneeboardPage): ) writer.heading("Flight Plan") - flight_plan_builder = FlightPlanBuilder(self.start_time) + flight_plan_builder = FlightPlanBuilder( + self.start_time, self.flight.aircraft_type.metric_kneeboard + ) for num, waypoint in enumerate(self.flight.waypoints): flight_plan_builder.add_waypoint(num, waypoint) writer.table( @@ -359,6 +385,7 @@ class BriefingPage(KneeboardPage): "Action", "Alt", "Dist", + "Brg", "GSPD", "Time", "Departure", diff --git a/game/missiongenerator/tgogenerator.py b/game/missiongenerator/tgogenerator.py index 3b80ec9f..cd54ae34 100644 --- a/game/missiongenerator/tgogenerator.py +++ b/game/missiongenerator/tgogenerator.py @@ -644,6 +644,15 @@ class HelipadGenerator: ).point_from_heading(helipad.heading.degrees + 90, 10), heading=pad.heading, ) + self.m.static_group( + country=country, + name=(name + "_ws"), + _type=Fortification.Windsock, + position=pad.position.point_from_heading( + helipad.heading.degrees + 45, 35 + ), + heading=pad.heading, + ) class TgoGenerator: diff --git a/resources/units/aircraft/Mi-24P.yaml b/resources/units/aircraft/Mi-24P.yaml index 4510182a..57325146 100644 --- a/resources/units/aircraft/Mi-24P.yaml +++ b/resources/units/aircraft/Mi-24P.yaml @@ -19,5 +19,6 @@ manufacturer: Mil origin: USSR/Russia price: 14 role: Attack/Transport +metric_kneeboard: true variants: Mi-24P Hind-F: {}