diff --git a/game/dcs/aircrafttype.py b/game/dcs/aircrafttype.py index 826f19de..4d42bb3e 100644 --- a/game/dcs/aircrafttype.py +++ b/game/dcs/aircrafttype.py @@ -33,7 +33,11 @@ from game.radio.channels import ( from game.utils import ( Distance, SPEED_OF_SOUND_AT_SEA_LEVEL, + ImperialUnits, + MetricUnits, + NauticalUnits, Speed, + UnitSystem, feet, knots, kph, @@ -154,8 +158,8 @@ 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 + # UnitSystem to use for the kneeboard, defaults to Nautical (kt/nm/ft) + kneeboard_units: UnitSystem # If true, kneeboards will display zulu times utc_kneeboard: bool @@ -376,6 +380,13 @@ class AircraftType(UnitType[Type[FlyingType]]): except KeyError: introduction = "No data." + units_data = data.get("kneeboard_units", "nautical").lower() + units: UnitSystem = NauticalUnits() + if units_data == "imperial": + units = ImperialUnits() + if units_data == "metric": + units = MetricUnits() + for variant in data.get("variants", [aircraft.id]): yield AircraftType( dcs_unit_type=aircraft, @@ -401,6 +412,6 @@ 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), + kneeboard_units=units, utc_kneeboard=data.get("utc_kneeboard", False), ) diff --git a/game/missiongenerator/kneeboard.py b/game/missiongenerator/kneeboard.py index a745ff8d..59164542 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 Distance, meters +from game.utils import Distance, UnitSystem, meters, mps, pounds from game.weather import Weather from gen.runways import RunwayData from .aircraft.flightdata import FlightData @@ -202,12 +202,12 @@ class FlightPlanBuilder: WAYPOINT_DESC_MAX_LEN = 25 - def __init__(self, start_time: datetime.datetime, is_metric: bool) -> None: + def __init__(self, start_time: datetime.datetime, units: UnitSystem) -> 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 + self.units = units def add_waypoint(self, waypoint_num: int, waypoint: FlightWaypoint) -> None: if waypoint.waypoint_type == FlightWaypointType.TARGET_POINT: @@ -269,32 +269,24 @@ class FlightPlanBuilder: return f"{local_time.strftime('%H:%M:%S')}{'Z' if local_time.tzinfo is not None else ''}" def _format_alt(self, alt: Distance) -> str: - if self.is_metric: - return f"{alt.meters:.0f} m" - else: - return f"{alt.feet:.0f} ft" + return f"{self.units.distance_short(alt):.0f}" def _waypoint_distance(self, waypoint: FlightWaypoint) -> str: if self.last_waypoint is None: return "-" - 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" + distance = meters( + self.last_waypoint.position.distance_to_point(waypoint.position) + ) + + return f"{self.units.distance_long(distance):.1f}" 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" + return f"{(bearing):.0f}" def _ground_speed(self, waypoint: FlightWaypoint) -> str: if self.last_waypoint is None: @@ -310,20 +302,19 @@ class FlightPlanBuilder: else: return "-" - distance = meters( + speed = mps( self.last_waypoint.position.distance_to_point(waypoint.position) + / (waypoint.tot - last_time).total_seconds() ) - duration = (waypoint.tot - last_time).total_seconds() / 3600 - 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: + return f"{self.units.speed(speed):.0f}" + + def _format_min_fuel(self, min_fuel: Optional[float]) -> str: if min_fuel is None: return "" - return str(math.ceil(min_fuel / 100) * 100) + + mass = pounds(min_fuel) + return f"{math.ceil(self.units.mass(mass) / 100) * 100:.0f}" def build(self) -> List[List[str]]: return self.rows @@ -373,13 +364,29 @@ class BriefingPage(KneeboardPage): ) writer.heading("Flight Plan") - flight_plan_builder = FlightPlanBuilder( - self.start_time, self.flight.aircraft_type.metric_kneeboard - ) + + units = self.flight.aircraft_type.kneeboard_units + + flight_plan_builder = FlightPlanBuilder(self.start_time, units) for num, waypoint in enumerate(self.flight.waypoints): flight_plan_builder.add_waypoint(num, waypoint) + + uom_row = [ + [ + "", + "", + units.distance_short_uom, + units.distance_long_uom, + "T", + units.speed_uom, + "", + "", + units.mass_uom, + ] + ] + writer.table( - flight_plan_builder.build(), + flight_plan_builder.build() + uom_row, headers=[ "#", "Action", @@ -404,15 +411,18 @@ class BriefingPage(KneeboardPage): ) writer.text(f"QNH: {qnh_in_hg} inHg / {qnh_mm_hg} mmHg / {qnh_hpa} hPa") - writer.table( - [ + fl = self.flight + + if fl.bingo_fuel and fl.joker_fuel: + writer.table( [ - "{}lbs".format(self.flight.bingo_fuel), - "{}lbs".format(self.flight.joker_fuel), - ] - ], - ["Bingo", "Joker"], - ) + [ + f"{units.mass(pounds(fl.bingo_fuel)):.0f} {units.mass_uom}", + f"{units.mass(pounds(fl.joker_fuel)):.0f} {units.mass_uom}", + ] + ], + ["Bingo", "Joker"], + ) if any(self.flight.laser_codes): codes: list[list[str]] = [] diff --git a/game/utils.py b/game/utils.py index 932d0151..479d65e0 100644 --- a/game/utils.py +++ b/game/utils.py @@ -1,4 +1,5 @@ from __future__ import annotations +from abc import ABC, abstractmethod import itertools import math @@ -14,16 +15,149 @@ METERS_TO_FEET = 3.28084 FEET_TO_METERS = 1 / METERS_TO_FEET NM_TO_METERS = 1852 METERS_TO_NM = 1 / NM_TO_METERS +MILES_TO_METERS = 1609.34 +METERS_TO_MILES = 1 / MILES_TO_METERS KNOTS_TO_KPH = 1.852 KPH_TO_KNOTS = 1 / KNOTS_TO_KPH MS_TO_KPH = 3.6 KPH_TO_MS = 1 / MS_TO_KPH +KPH_TO_MPH = 0.621371 +MPH_TO_KPH = 1 / KPH_TO_MPH INHG_TO_HPA = 33.86389 INHG_TO_MMHG = 25.400002776728 LBS_TO_KG = 0.453592 +KG_TO_LBS = 1 / LBS_TO_KG + + +class UnitSystem(ABC): + @abstractmethod + def distance_short(self, dist: Distance) -> float: + pass + + @abstractmethod + def distance_long(self, dist: Distance) -> float: + pass + + @property + @abstractmethod + def distance_short_uom(self) -> str: + pass + + @property + @abstractmethod + def distance_long_uom(self) -> str: + pass + + @abstractmethod + def speed(self, speed: Speed) -> float: + pass + + @property + @abstractmethod + def speed_uom(self) -> str: + pass + + @abstractmethod + def mass(self, mass: Mass) -> float: + pass + + @property + @abstractmethod + def mass_uom(self) -> str: + pass + + +class NauticalUnits(UnitSystem): + def distance_short(self, dist: Distance) -> float: + return dist.feet + + def distance_long(self, dist: Distance) -> float: + return dist.nautical_miles + + @property + def distance_short_uom(self) -> str: + return "ft" + + @property + def distance_long_uom(self) -> str: + return "nm" + + def speed(self, speed: Speed) -> float: + return speed.knots + + @property + def speed_uom(self) -> str: + return "kt" + + def mass(self, mass: Mass) -> float: + return mass.pounds + + @property + def mass_uom(self) -> str: + return "lb" + + +class MetricUnits(UnitSystem): + def distance_short(self, dist: Distance) -> float: + return dist.meters + + def distance_long(self, dist: Distance) -> float: + return dist.kilometers + + @property + def distance_short_uom(self) -> str: + return "m" + + @property + def distance_long_uom(self) -> str: + return "km" + + def speed(self, speed: Speed) -> float: + return speed.kph + + @property + def speed_uom(self) -> str: + return "kph" + + def mass(self, mass: Mass) -> float: + return mass.kgs + + @property + def mass_uom(self) -> str: + return "kg" + + +class ImperialUnits(UnitSystem): + def distance_short(self, dist: Distance) -> float: + return dist.feet + + def distance_long(self, dist: Distance) -> float: + return dist.miles + + @property + def distance_short_uom(self) -> str: + return "ft" + + @property + def distance_long_uom(self) -> str: + return "m" + + def speed(self, speed: Speed) -> float: + return speed.mph + + @property + def speed_uom(self) -> str: + return "mph" + + def mass(self, mass: Mass) -> float: + return mass.pounds + + @property + def mass_uom(self) -> str: + return "lb" @dataclass(frozen=True) @@ -42,6 +176,14 @@ class Distance: def nautical_miles(self) -> float: return self.distance_in_meters * METERS_TO_NM + @property + def kilometers(self) -> float: + return self.distance_in_meters / 1000 + + @property + def miles(self) -> float: + return self.distance_in_meters * METERS_TO_MILES + @classmethod def from_feet(cls, value: float) -> Distance: return cls(value * FEET_TO_METERS) @@ -119,6 +261,10 @@ class Speed: def meters_per_second(self) -> float: return self.speed_in_kph * KPH_TO_MS + @property + def mph(self) -> float: + return self.speed_in_kph * KPH_TO_MPH + def mach(self, altitude: Distance = meters(0)) -> float: c_sound = mach(1, altitude) return self.speed_in_kph / c_sound.kph @@ -272,6 +418,27 @@ def inches_hg(value: float) -> Pressure: return Pressure(value) +@dataclass(frozen=True, order=True) +class Mass: + mass_in_kg: float + + @property + def pounds(self) -> float: + return self.mass_in_kg * KG_TO_LBS + + @property + def kgs(self) -> float: + return self.mass_in_kg + + +def pounds(value: float) -> Mass: + return Mass(value * LBS_TO_KG) + + +def kgs(value: float) -> Mass: + return Mass(value) + + PairwiseT = TypeVar("PairwiseT") diff --git a/resources/units/aircraft/AJS37.yaml b/resources/units/aircraft/AJS37.yaml index a4aa0fdb..245b1280 100644 --- a/resources/units/aircraft/AJS37.yaml +++ b/resources/units/aircraft/AJS37.yaml @@ -29,3 +29,4 @@ radios: channels: type: viggen namer: viggen +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/Bf-109K-4.yaml b/resources/units/aircraft/Bf-109K-4.yaml index b4f54973..08c26f4b 100644 --- a/resources/units/aircraft/Bf-109K-4.yaml +++ b/resources/units/aircraft/Bf-109K-4.yaml @@ -17,3 +17,4 @@ role: Fighter gunfighter: true variants: "Bf 109 K-4 Kurf\xFCrst": {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/FW-190A8.yaml b/resources/units/aircraft/FW-190A8.yaml index d9074fdb..1cfbc790 100644 --- a/resources/units/aircraft/FW-190A8.yaml +++ b/resources/units/aircraft/FW-190A8.yaml @@ -28,3 +28,4 @@ role: Fighter gunfighter: true variants: Fw 190 A-8 Anton: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/FW-190D9.yaml b/resources/units/aircraft/FW-190D9.yaml index ec23af0c..4e19dba7 100644 --- a/resources/units/aircraft/FW-190D9.yaml +++ b/resources/units/aircraft/FW-190D9.yaml @@ -17,3 +17,4 @@ role: Fighter gunfighter: true variants: Fw 190 D-9 Dora: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/J-11A.yaml b/resources/units/aircraft/J-11A.yaml index 2c26fc33..d0c16d1f 100644 --- a/resources/units/aircraft/J-11A.yaml +++ b/resources/units/aircraft/J-11A.yaml @@ -10,3 +10,4 @@ price: 22 role: Air-Superiority Fighter variants: J-11A Flanker-L: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/Ka-50.yaml b/resources/units/aircraft/Ka-50.yaml index e595531e..8391235d 100644 --- a/resources/units/aircraft/Ka-50.yaml +++ b/resources/units/aircraft/Ka-50.yaml @@ -20,3 +20,4 @@ radios: # The R-800L1 doesn't have preset channels, and the other radio is for # communications with FAC and ground units, which don't currently have # radios assigned, so no channels to configure. +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/L-39ZA.yaml b/resources/units/aircraft/L-39ZA.yaml index d8b80fd9..744eaf43 100644 --- a/resources/units/aircraft/L-39ZA.yaml +++ b/resources/units/aircraft/L-39ZA.yaml @@ -12,3 +12,4 @@ role: Light Attack gunfighter: true variants: L-39ZA Albatros: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/Mi-24P.yaml b/resources/units/aircraft/Mi-24P.yaml index 57325146..10463359 100644 --- a/resources/units/aircraft/Mi-24P.yaml +++ b/resources/units/aircraft/Mi-24P.yaml @@ -19,6 +19,6 @@ manufacturer: Mil origin: USSR/Russia price: 14 role: Attack/Transport -metric_kneeboard: true +kneeboard_units: "metric" variants: Mi-24P Hind-F: {} diff --git a/resources/units/aircraft/Mi-8MT.yaml b/resources/units/aircraft/Mi-8MT.yaml index 95ec5e8f..0fe0ad20 100644 --- a/resources/units/aircraft/Mi-8MT.yaml +++ b/resources/units/aircraft/Mi-8MT.yaml @@ -10,3 +10,4 @@ price: 5 role: Transport/Light Attack variants: Mi-8MTV2 Hip: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/MiG-15bis.yaml b/resources/units/aircraft/MiG-15bis.yaml index 82aaa9be..195022ee 100644 --- a/resources/units/aircraft/MiG-15bis.yaml +++ b/resources/units/aircraft/MiG-15bis.yaml @@ -21,3 +21,4 @@ variants: radios: intra_flight: RSI-6K HF inter_flight: RSI-6K HF +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/MiG-19P.yaml b/resources/units/aircraft/MiG-19P.yaml index 0187b492..13d5fb91 100644 --- a/resources/units/aircraft/MiG-19P.yaml +++ b/resources/units/aircraft/MiG-19P.yaml @@ -27,3 +27,4 @@ radios: channels: type: farmer namer: single +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/MiG-21Bis.yaml b/resources/units/aircraft/MiG-21Bis.yaml index 0339fbb0..656298eb 100644 --- a/resources/units/aircraft/MiG-21Bis.yaml +++ b/resources/units/aircraft/MiG-21Bis.yaml @@ -27,3 +27,4 @@ radios: namer: single intra_flight_radio_index: 1 inter_flight_radio_index: 1 +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/MiG-29A.yaml b/resources/units/aircraft/MiG-29A.yaml index c9ab10fc..b191f370 100644 --- a/resources/units/aircraft/MiG-29A.yaml +++ b/resources/units/aircraft/MiG-29A.yaml @@ -28,3 +28,4 @@ role: Multirole Fighter max_range: 150 variants: MiG-29A Fulcrum-A: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/MiG-29G.yaml b/resources/units/aircraft/MiG-29G.yaml index 8c0059bb..45d374f8 100644 --- a/resources/units/aircraft/MiG-29G.yaml +++ b/resources/units/aircraft/MiG-29G.yaml @@ -28,3 +28,4 @@ role: Multirole Fighter max_range: 150 variants: MiG-29G Fulcrum-A: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/MiG-29S.yaml b/resources/units/aircraft/MiG-29S.yaml index 25ab27d6..58f13fc5 100644 --- a/resources/units/aircraft/MiG-29S.yaml +++ b/resources/units/aircraft/MiG-29S.yaml @@ -28,3 +28,4 @@ role: Multirole Fighter max_range: 150 variants: MiG-29S Fulcrum-C: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/MosquitoFBMkVI.yaml b/resources/units/aircraft/MosquitoFBMkVI.yaml index 39f796e6..8aa3974b 100644 --- a/resources/units/aircraft/MosquitoFBMkVI.yaml +++ b/resources/units/aircraft/MosquitoFBMkVI.yaml @@ -6,3 +6,4 @@ price: 6 role: Light Bomber, Fighter Bomber, Night Fighter, Maritime Strike Aircraft, Photo Recon Aircraft variants: MosquitoFBMkVI: {} +kneeboard_units: "imperial" \ No newline at end of file diff --git a/resources/units/aircraft/P-47D-30.yaml b/resources/units/aircraft/P-47D-30.yaml index 9a78cd5d..3ba0a665 100644 --- a/resources/units/aircraft/P-47D-30.yaml +++ b/resources/units/aircraft/P-47D-30.yaml @@ -29,3 +29,4 @@ radios: channels: type: SCR-522 namer: SCR-522 +kneeboard_units: "imperial" \ No newline at end of file diff --git a/resources/units/aircraft/P-47D-30bl1.yaml b/resources/units/aircraft/P-47D-30bl1.yaml index d27002b0..4fd1172d 100644 --- a/resources/units/aircraft/P-47D-30bl1.yaml +++ b/resources/units/aircraft/P-47D-30bl1.yaml @@ -29,3 +29,4 @@ radios: channels: type: SCR-522 namer: SCR-522 +kneeboard_units: "imperial" \ No newline at end of file diff --git a/resources/units/aircraft/P-47D-40.yaml b/resources/units/aircraft/P-47D-40.yaml index 748b1d85..5b6a2613 100644 --- a/resources/units/aircraft/P-47D-40.yaml +++ b/resources/units/aircraft/P-47D-40.yaml @@ -28,4 +28,5 @@ radios: inter_flight: SCR522 channels: type: SCR-522 - namer: SCR-522 \ No newline at end of file + namer: SCR-522 +kneeboard_units: "imperial" \ No newline at end of file diff --git a/resources/units/aircraft/P-51D-30-NA.yaml b/resources/units/aircraft/P-51D-30-NA.yaml index e9591bee..77734f0d 100644 --- a/resources/units/aircraft/P-51D-30-NA.yaml +++ b/resources/units/aircraft/P-51D-30-NA.yaml @@ -30,3 +30,4 @@ radios: channels: type: SCR-522 namer: SCR-522 +kneeboard_units: "imperial" \ No newline at end of file diff --git a/resources/units/aircraft/P-51D.yaml b/resources/units/aircraft/P-51D.yaml index a67ddc06..fb3af65c 100644 --- a/resources/units/aircraft/P-51D.yaml +++ b/resources/units/aircraft/P-51D.yaml @@ -30,3 +30,4 @@ radios: channels: type: SCR-522 namer: SCR-522 +kneeboard_units: "imperial" \ No newline at end of file diff --git a/resources/units/aircraft/SA342L.yaml b/resources/units/aircraft/SA342L.yaml index 3f9a3d99..4c1384f4 100644 --- a/resources/units/aircraft/SA342L.yaml +++ b/resources/units/aircraft/SA342L.yaml @@ -15,3 +15,4 @@ price: 5 role: Light Attack variants: SA 342L Gazelle: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/SA342M.yaml b/resources/units/aircraft/SA342M.yaml index 46166e4a..02ac8cad 100644 --- a/resources/units/aircraft/SA342M.yaml +++ b/resources/units/aircraft/SA342M.yaml @@ -18,3 +18,4 @@ variants: introduced: 1974 manufacturer: Westland SA 342M Gazelle: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/SA342Minigun.yaml b/resources/units/aircraft/SA342Minigun.yaml index 14d44082..99da8f7e 100644 --- a/resources/units/aircraft/SA342Minigun.yaml +++ b/resources/units/aircraft/SA342Minigun.yaml @@ -1,3 +1,4 @@ price: 4 variants: SA342Minigun: null +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/SA342Mistral.yaml b/resources/units/aircraft/SA342Mistral.yaml index 1fc101ec..abbc0ebb 100644 --- a/resources/units/aircraft/SA342Mistral.yaml +++ b/resources/units/aircraft/SA342Mistral.yaml @@ -15,3 +15,4 @@ price: 8 role: Light Attack variants: SA 342M Gazelle Mistral: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/SpitfireLFMkIX.yaml b/resources/units/aircraft/SpitfireLFMkIX.yaml index 2bfc95ab..de962530 100644 --- a/resources/units/aircraft/SpitfireLFMkIX.yaml +++ b/resources/units/aircraft/SpitfireLFMkIX.yaml @@ -41,3 +41,4 @@ role: Fighter gunfighter: true variants: Spitfire LF Mk IX: {} +kneeboard_units: "imperial" \ No newline at end of file diff --git a/resources/units/aircraft/SpitfireLFMkIXCW.yaml b/resources/units/aircraft/SpitfireLFMkIXCW.yaml index 1f94bd22..55d9d2ae 100644 --- a/resources/units/aircraft/SpitfireLFMkIXCW.yaml +++ b/resources/units/aircraft/SpitfireLFMkIXCW.yaml @@ -41,3 +41,4 @@ role: Fighter gunfighter: true variants: Spitfire LF Mk IX (Clipped Wings): {} +kneeboard_units: "imperial" \ No newline at end of file diff --git a/resources/units/aircraft/Su-25.yaml b/resources/units/aircraft/Su-25.yaml index 8c425bc3..ede47950 100644 --- a/resources/units/aircraft/Su-25.yaml +++ b/resources/units/aircraft/Su-25.yaml @@ -14,3 +14,4 @@ role: Close Air Support/Attack max_range: 200 variants: Su-25 Frogfoot: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/Su-25T.yaml b/resources/units/aircraft/Su-25T.yaml index 0059c2ca..6b285f35 100644 --- a/resources/units/aircraft/Su-25T.yaml +++ b/resources/units/aircraft/Su-25T.yaml @@ -14,3 +14,4 @@ role: Close Air Support/Attack max_range: 200 variants: Su-25T Frogfoot: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/Su-27.yaml b/resources/units/aircraft/Su-27.yaml index da9f3c87..167a4e70 100644 --- a/resources/units/aircraft/Su-27.yaml +++ b/resources/units/aircraft/Su-27.yaml @@ -17,3 +17,4 @@ role: Air-Superiority Fighter max_range: 300 variants: Su-27 Flanker-B: {} +kneeboard_units: "metric" \ No newline at end of file diff --git a/resources/units/aircraft/Su-33.yaml b/resources/units/aircraft/Su-33.yaml index 1b6568da..7ad7fe69 100644 --- a/resources/units/aircraft/Su-33.yaml +++ b/resources/units/aircraft/Su-33.yaml @@ -29,3 +29,4 @@ variants: origin: China role: Carrier-based Multirole Fighter Su-33 Flanker-D: {} +kneeboard_units: "metric" \ No newline at end of file