mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Adds prettier user-facing aircraft names. (#726)
This makes the names of the aircraft displayed to the player in the UI more verbose and readable. It allows allows specific countries to display an aircraft's name differently. An example of this would be the JF-17 Thunder, which is known in China as the FC-1 Fierce Dragon - this now displays correctly in the Liberation UI.
This commit is contained in:
parent
c3401d478b
commit
c740c8304b
@ -20,6 +20,7 @@ Saves from 2.3 are not compatible with 2.4.
|
||||
* **[Economy]** Carriers and off-map spawns generate no income (previously $20M like airbases).
|
||||
* **[Economy]** Sales of aircraft and ground vehicles can now be cancelled before the next turn begins.
|
||||
* **[UI]** Multi-SAM objectives now show threat and detection rings per group.
|
||||
* **[UI]** Unit names are now prettier and more accurate, and can now be set per-country for added historical flavour.
|
||||
* **[Factions]** Added option for date-based loadout restriction. Active radar homing missiles are handled, patches welcome for the other thousand weapons.
|
||||
* **[Factions]** Added Poland 2010 faction.
|
||||
* **[Factions]** Added Greece 2005 faction.
|
||||
|
||||
23
game/db.py
23
game/db.py
@ -1,6 +1,8 @@
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import Dict, List, Optional, Tuple, Type, Union
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from dcs.countries import country_dict
|
||||
from dcs.helicopters import (
|
||||
@ -169,6 +171,8 @@ from pydcs_extensions.mb339.mb339 import MB_339PAN
|
||||
from pydcs_extensions.rafale.rafale import Rafale_A_S, Rafale_M, Rafale_B
|
||||
from pydcs_extensions.su57.su57 import Su_57
|
||||
|
||||
PRETTYNAMES_PATH = Path("./resources/units/pretty_unit_names.json")
|
||||
|
||||
plane_map["A-4E-C"] = A_4E_C
|
||||
plane_map["MB-339PAN"] = MB_339PAN
|
||||
plane_map["Rafale_M"] = Rafale_M
|
||||
@ -1321,6 +1325,25 @@ def unit_type_name(unit_type) -> str:
|
||||
def unit_type_name_2(unit_type) -> str:
|
||||
return unit_type.name and unit_type.name or unit_type.id
|
||||
|
||||
def unit_pretty_name(country_name: str, unit_type) -> str:
|
||||
original_name = unit_type.name and unit_type.name or unit_type.id
|
||||
default_name = None
|
||||
faction_name = None
|
||||
with PRETTYNAMES_PATH.open("r", encoding="utf-8") as fdata:
|
||||
data = json.load(fdata, encoding="utf-8")
|
||||
type_exists = data.get(original_name)
|
||||
if type_exists is None:
|
||||
return original_name
|
||||
for faction in type_exists:
|
||||
if default_name is None:
|
||||
default_name = faction.get("default")
|
||||
if faction_name is None:
|
||||
faction_name = faction.get(country_name)
|
||||
if default_name is None:
|
||||
return original_name
|
||||
if faction_name is None:
|
||||
return default_name
|
||||
return faction_name
|
||||
|
||||
def unit_type_from_name(name: str) -> Optional[Type[UnitType]]:
|
||||
if name in vehicle_map:
|
||||
|
||||
@ -262,6 +262,9 @@ class FlightData:
|
||||
#: The package that the flight belongs to.
|
||||
package: Package
|
||||
|
||||
#: The country that the flight belongs to.
|
||||
country: str
|
||||
|
||||
flight_type: FlightType
|
||||
|
||||
#: All units in the flight.
|
||||
@ -299,7 +302,7 @@ class FlightData:
|
||||
|
||||
joker_fuel: Optional[int]
|
||||
|
||||
def __init__(self, package: Package, flight_type: FlightType,
|
||||
def __init__(self, package: Package, country: str, flight_type: FlightType,
|
||||
units: List[FlyingUnit], size: int, friendly: bool,
|
||||
departure_delay: timedelta, departure: RunwayData,
|
||||
arrival: RunwayData, divert: Optional[RunwayData],
|
||||
@ -308,6 +311,7 @@ class FlightData:
|
||||
bingo_fuel: Optional[int],
|
||||
joker_fuel: Optional[int]) -> None:
|
||||
self.package = package
|
||||
self.country = country
|
||||
self.flight_type = flight_type
|
||||
self.units = units
|
||||
self.size = size
|
||||
@ -778,6 +782,7 @@ class AircraftConflictGenerator:
|
||||
|
||||
self.flights.append(FlightData(
|
||||
package=package,
|
||||
country=faction.country,
|
||||
flight_type=flight.flight_type,
|
||||
units=group.units,
|
||||
size=len(group.units),
|
||||
@ -984,7 +989,7 @@ class AircraftConflictGenerator:
|
||||
# Creating a flight even those this isn't a fragged mission lets us
|
||||
# reuse the existing debriefing code.
|
||||
# TODO: Special flight type?
|
||||
flight = Flight(Package(control_point), aircraft, 1,
|
||||
flight = Flight(Package(control_point), faction.country, aircraft, 1,
|
||||
FlightType.BARCAP, "Cold", departure=control_point,
|
||||
arrival=control_point, divert=None)
|
||||
|
||||
|
||||
@ -173,9 +173,11 @@ class PackageBuilder:
|
||||
closest_airfields: ClosestAirfields,
|
||||
global_inventory: GlobalAircraftInventory,
|
||||
is_player: bool,
|
||||
package_country: str,
|
||||
start_type: str) -> None:
|
||||
self.closest_airfields = closest_airfields
|
||||
self.is_player = is_player
|
||||
self.package_country = package_country
|
||||
self.package = Package(location)
|
||||
self.allocator = AircraftAllocator(closest_airfields, global_inventory,
|
||||
is_player)
|
||||
@ -199,7 +201,7 @@ class PackageBuilder:
|
||||
else:
|
||||
start_type = self.start_type
|
||||
|
||||
flight = Flight(self.package, aircraft, plan.num_aircraft, plan.task,
|
||||
flight = Flight(self.package, self.package_country, aircraft, plan.num_aircraft, plan.task,
|
||||
start_type, departure=airfield, arrival=airfield,
|
||||
divert=self.find_divert_field(aircraft, airfield))
|
||||
self.package.add_flight(flight)
|
||||
@ -629,11 +631,17 @@ class CoalitionMissionPlanner:
|
||||
else:
|
||||
start_type = "Warm"
|
||||
|
||||
if self.is_player:
|
||||
package_country = self.game.player_country
|
||||
else:
|
||||
package_country = self.game.enemy_country
|
||||
|
||||
builder = PackageBuilder(
|
||||
mission.location,
|
||||
self.objective_finder.closest_airfields_to(mission.location),
|
||||
self.game.aircraft_inventory,
|
||||
self.is_player,
|
||||
package_country,
|
||||
start_type
|
||||
)
|
||||
|
||||
|
||||
@ -136,12 +136,13 @@ class FlightWaypoint:
|
||||
|
||||
class Flight:
|
||||
|
||||
def __init__(self, package: Package, unit_type: Type[FlyingType],
|
||||
def __init__(self, package: Package, country: str, unit_type: Type[FlyingType],
|
||||
count: int, flight_type: FlightType, start_type: str,
|
||||
departure: ControlPoint, arrival: ControlPoint,
|
||||
divert: Optional[ControlPoint],
|
||||
custom_name: Optional[str] = None) -> None:
|
||||
self.package = package
|
||||
self.country = country
|
||||
self.unit_type = unit_type
|
||||
self.count = count
|
||||
self.departure = departure
|
||||
@ -179,3 +180,9 @@ class Flight:
|
||||
if self.custom_name:
|
||||
return f"{self.custom_name} {self.count} x {name}"
|
||||
return f"[{self.flight_type}] {self.count} x {name}"
|
||||
|
||||
def __str__(self):
|
||||
name = db.unit_pretty_name(self.country, self.unit_type)
|
||||
if self.custom_name:
|
||||
return f"{self.custom_name} {self.count} x {name}"
|
||||
return f"[{self.flight_type}] {self.count} x {name}"
|
||||
|
||||
@ -5,12 +5,13 @@ from PySide2.QtWidgets import QComboBox
|
||||
|
||||
from dcs.unittype import FlyingType
|
||||
|
||||
from game import Game, db
|
||||
|
||||
class QAircraftTypeSelector(QComboBox):
|
||||
"""Combo box for selecting among the given aircraft types."""
|
||||
|
||||
def __init__(self, aircraft_types: Iterable[Type[FlyingType]]) -> None:
|
||||
def __init__(self, aircraft_types: Iterable[Type[FlyingType]], country: str) -> None:
|
||||
super().__init__()
|
||||
for aircraft in aircraft_types:
|
||||
self.addItem(f"{aircraft.id}", userData=aircraft)
|
||||
self.addItem(f"{db.unit_pretty_name(country, aircraft)}", userData=aircraft)
|
||||
self.model().sort(0)
|
||||
|
||||
@ -52,7 +52,7 @@ class QDebriefingWindow(QDialog):
|
||||
for unit_type, count in player_air_losses.items():
|
||||
try:
|
||||
lostUnitsLayout.addWidget(
|
||||
QLabel(db.unit_type_name(unit_type)), row, 0)
|
||||
QLabel(db.unit_pretty_name(self.debriefing.player_country, unit_type)), row, 0)
|
||||
lostUnitsLayout.addWidget(QLabel(str(count)), row, 1)
|
||||
row += 1
|
||||
except AttributeError:
|
||||
@ -94,7 +94,7 @@ class QDebriefingWindow(QDialog):
|
||||
for unit_type, count in enemy_air_losses.items():
|
||||
try:
|
||||
enemylostUnitsLayout.addWidget(
|
||||
QLabel(db.unit_type_name(unit_type)), row, 0)
|
||||
QLabel(db.unit_pretty_name(self.debriefing.enemy_country, unit_type)), row, 0)
|
||||
enemylostUnitsLayout.addWidget(QLabel(str(count)), row, 1)
|
||||
row += 1
|
||||
except AttributeError:
|
||||
|
||||
@ -58,7 +58,7 @@ class QRecruitBehaviour:
|
||||
existing_units = self.cp.base.total_units_of_type(unit_type)
|
||||
scheduled_units = self.pending_deliveries.units.get(unit_type, 0)
|
||||
|
||||
unitName = QLabel("<b>" + db.unit_type_name_2(unit_type) + "</b>")
|
||||
unitName = QLabel("<b>" + db.unit_pretty_name(self.game_model.game.player_country, unit_type) + "</b>")
|
||||
unitName.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
||||
|
||||
existing_units = QLabel(str(existing_units))
|
||||
|
||||
@ -46,7 +46,7 @@ class QIntelInfo(QFrame):
|
||||
existing_units = self.cp.base.total_units_of_type(unit_type)
|
||||
if existing_units == 0:
|
||||
continue
|
||||
groupLayout.addWidget(QLabel("<b>" + db.unit_type_name(unit_type) + "</b>"), row, 0)
|
||||
groupLayout.addWidget(QLabel("<b>" + db.unit_pretty_name(self.game.enemy_country, unit_type) + "</b>"), row, 0)
|
||||
groupLayout.addWidget(QLabel(str(existing_units)), row, 1)
|
||||
row += 1
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ from PySide2.QtWidgets import (
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from game.game import Game
|
||||
from game.game import Game, db
|
||||
from qt_ui.uiconstants import ICONS
|
||||
from qt_ui.windows.finances.QFinancesMenu import FinancesLayout
|
||||
|
||||
@ -81,7 +81,7 @@ class AircraftIntelLayout(IntelTableLayout):
|
||||
for airframe, count in base.aircraft.items():
|
||||
if not count:
|
||||
continue
|
||||
self.add_row(airframe.id, count)
|
||||
self.add_row(db.unit_pretty_name(game.enemy_country, airframe), count)
|
||||
|
||||
self.add_spacer()
|
||||
self.add_row("<b>Total</b>", total)
|
||||
|
||||
@ -34,6 +34,7 @@ class QFlightCreator(QDialog):
|
||||
self.game = game
|
||||
self.package = package
|
||||
self.custom_name_text = None
|
||||
self.country = self.game.player_country
|
||||
|
||||
self.setWindowTitle("Create flight")
|
||||
self.setWindowIcon(EVENT_ICONS["strike"])
|
||||
@ -47,7 +48,7 @@ class QFlightCreator(QDialog):
|
||||
layout.addLayout(QLabeledWidget("Task:", self.task_selector))
|
||||
|
||||
self.aircraft_selector = QAircraftTypeSelector(
|
||||
self.game.aircraft_inventory.available_types_for_player
|
||||
self.game.aircraft_inventory.available_types_for_player, self.game.player_country
|
||||
)
|
||||
self.aircraft_selector.setCurrentIndex(0)
|
||||
self.aircraft_selector.currentIndexChanged.connect(
|
||||
@ -154,7 +155,7 @@ class QFlightCreator(QDialog):
|
||||
start_type = "Cold"
|
||||
else:
|
||||
start_type = "Warm"
|
||||
flight = Flight(self.package, aircraft, size, task, start_type, origin,
|
||||
flight = Flight(self.package, self.country, aircraft, size, task, start_type, origin,
|
||||
arrival, divert, custom_name=self.custom_name_text)
|
||||
flight.client_count = self.client_slots_spinner.value()
|
||||
|
||||
|
||||
271
resources/units/pretty_unit_names.json
Normal file
271
resources/units/pretty_unit_names.json
Normal file
@ -0,0 +1,271 @@
|
||||
{
|
||||
"A-10A": [{
|
||||
"default": "A-10A Thunderbolt II"
|
||||
}],
|
||||
"A-10C": [{
|
||||
"default": "A-10C Thunderbolt II (Suite 3)"
|
||||
}],
|
||||
"A-10C_2": [{
|
||||
"default": "A-10C Thunderbolt II (Suite 7)"
|
||||
}],
|
||||
"A-20G": [{
|
||||
"default": "A-20G Havoc",
|
||||
"UK": "Boston Mk.III"
|
||||
}],
|
||||
"A-4E-C": [{
|
||||
"default": "A-4E Skyhawk"
|
||||
}],
|
||||
"AH_1W": [{
|
||||
"default": "AH-1W SuperCobra"
|
||||
}],
|
||||
"AH-64A": [{
|
||||
"default": "AH-64A Apache"
|
||||
}],
|
||||
"AH-64D": [{
|
||||
"default": "AH-64D Apache Longbow"
|
||||
}],
|
||||
"AJS37": [{
|
||||
"default": "AJS-37 Viggen"
|
||||
}],
|
||||
"AV8BNA": [{
|
||||
"default": "AV-8B Harrier II Night Attack"
|
||||
}],
|
||||
"B-1B": [{
|
||||
"default": "B-1B Lancer"
|
||||
}],
|
||||
"B-17G": [{
|
||||
"default": "B-17G Flying Fortress",
|
||||
"UK": "Fortress Mk.III"
|
||||
}],
|
||||
"B-52H": [{
|
||||
"default": "B-52H Stratofortress"
|
||||
}],
|
||||
"Bf-109K-4": [{
|
||||
"default": "Bf 109 K-4 Kurfürst"
|
||||
}],
|
||||
"C-101CC": [{
|
||||
"default": "C-101CC Aviojet"
|
||||
}],
|
||||
"C-101EB": [{
|
||||
"default": "C-101EB Aviojet"
|
||||
}],
|
||||
"F-4E": [{
|
||||
"default": "F-4E Phantom II",
|
||||
"Germany": "F-4F Phantom II",
|
||||
"Japan": "F-4EJ Kai Phantom II",
|
||||
"UK": "Phantom F.3"
|
||||
}],
|
||||
"F-5E-3": [{
|
||||
"default": "F-5E Tiger II"
|
||||
}],
|
||||
"F-14A-135-GR": [{
|
||||
"default": "F-14A Tomcat (Block 135-GR Late)"
|
||||
}],
|
||||
"F-14B": [{
|
||||
"default": "F-14B Tomcat"
|
||||
}],
|
||||
"F-15C": [{
|
||||
"default": "F-15C Eagle",
|
||||
"Japan": "F-15J Eagle"
|
||||
}],
|
||||
"F-15E": [{
|
||||
"default": "F-15E Strike Eagle"
|
||||
}],
|
||||
"F-16C_50": [{
|
||||
"default": "F-16CM Fighting Falcon (Block 50)",
|
||||
"Japan": "F-2A"
|
||||
}],
|
||||
"F-22A":[{
|
||||
"default": "F-22A Raptor"
|
||||
}],
|
||||
"F-86F Sabre": [{
|
||||
"default": "F-86F Sabre"
|
||||
}],
|
||||
"F-111F": [{
|
||||
"default": "F-111F Aardvark"
|
||||
}],
|
||||
"F-117A": [{
|
||||
"default": "F-117A Nighthawk"
|
||||
}],
|
||||
"FA-18C_hornet": [{
|
||||
"default": "F/A-18C Hornet (Lot 20)",
|
||||
"Canada": "CF-188 Hornet",
|
||||
"Spain": "EF-18A+ Hornet"
|
||||
}],
|
||||
"FW-190A8": [{
|
||||
"default": "Fw 190 A-8 Anton"
|
||||
}],
|
||||
"FW-190D9": [{
|
||||
"default": "Fw 190 D-9 Dora"
|
||||
}],
|
||||
"Hercules": [{
|
||||
"default": "C-130J-30 Super Hercules"
|
||||
}],
|
||||
"I-16": [{
|
||||
"default": "I-16 Ishak"
|
||||
}],
|
||||
"J-11A": [{
|
||||
"default": "J-11A Flanker-L"
|
||||
}],
|
||||
"JF-17": [{
|
||||
"default": "JF-17 Thunder",
|
||||
"China": "FC-1 Fierce Dragon"
|
||||
}],
|
||||
"Ju-88A4": [{
|
||||
"default": "Ju 88 A-4"
|
||||
}],
|
||||
"Ka-50": [{
|
||||
"default": "Ka-50 Hokum"
|
||||
}],
|
||||
"L-39ZA": [{
|
||||
"default": "L-39ZA Albatross"
|
||||
}],
|
||||
"M-2000C": [{
|
||||
"default": "Mirage 2000C"
|
||||
}],
|
||||
"MB-339PAN":[{
|
||||
"default": "MB-339PAN"
|
||||
}],
|
||||
"Mirage 2000-5": [{
|
||||
"default": "Mirage 2000-5"
|
||||
}],
|
||||
"Mi-24V": [{
|
||||
"default": "Mi-24V Hind-E"
|
||||
}],
|
||||
"Mi-28N": [{
|
||||
"default": "Mi-28N Havoc"
|
||||
}],
|
||||
"Mi-8MT": [{
|
||||
"default": "Mi-8MTV2 Hip"
|
||||
}],
|
||||
"MiG-15bis": [{
|
||||
"default": "MiG-15bis Fagot"
|
||||
}],
|
||||
"MiG-19P": [{
|
||||
"default": "MiG-19P Farmer-B",
|
||||
"China": "J-6A"
|
||||
}],
|
||||
"MiG-21Bis": [{
|
||||
"default": "MiG-21bis Fishbed-N",
|
||||
"China": "J-7B"
|
||||
}],
|
||||
"MiG-23MLD": [{
|
||||
"default": "MiG-23MLD Flogger-K"
|
||||
}],
|
||||
"MiG-25PD": [{
|
||||
"default": "MiG-25PD Foxbat-E"
|
||||
}],
|
||||
"MiG-25RBT": [{
|
||||
"default": "MiG-25RBT Foxbat-B"
|
||||
}],
|
||||
"MiG_27K": [{
|
||||
"default": "MiG-27K Flogger-J2"
|
||||
}],
|
||||
"MiG-29A": [{
|
||||
"default": "MiG-29A Fulcrum-A"
|
||||
}],
|
||||
"MiG-29G": [{
|
||||
"default": "MiG-29G Fulcrum-A"
|
||||
}],
|
||||
"MiG-29S": [{
|
||||
"default": "MiG-29S Fulcrum-C"
|
||||
}],
|
||||
"MiG-31": [{
|
||||
"default": "MiG-31 Foxhound"
|
||||
}],
|
||||
"P-47D-30": [{
|
||||
"default": "P-47D-30 Thunderbolt (Late)",
|
||||
"UK": "Thunderbolt Mk.II (Mid)"
|
||||
}],
|
||||
"P-47D-30bl1": [{
|
||||
"default": "P-47D-30 Thunderbolt (Early)",
|
||||
"UK": "Thunderbolt Mk.II (Early)"
|
||||
}],
|
||||
"P-47D-40": [{
|
||||
"default": "P-47D-40 Thunderbolt",
|
||||
"UK": "Thunderbolt Mk.II (Late)"
|
||||
}],
|
||||
"P-51D": [{
|
||||
"default": "P-51D-25-NA Mustang",
|
||||
"UK": "Mustang Mk.IV (Early)"
|
||||
}],
|
||||
"P-51D-30-NA": [{
|
||||
"default": "P-51D-30-NA Mustang",
|
||||
"UK": "Mustang Mk.IV (Late)"
|
||||
}],
|
||||
"Rafale_A_S": [{
|
||||
"default": "Rafale M (Air-to-Ground)"
|
||||
}],
|
||||
"Rafale_B": [{
|
||||
"default": "Rafale B"
|
||||
}],
|
||||
"Rafale_M": [{
|
||||
"default": "Rafale M (Air-to-Air)"
|
||||
}],
|
||||
"S-3B": [{
|
||||
"default": "S-3B Viking"
|
||||
}],
|
||||
"SA342L": [{
|
||||
"default": "SA 342L Gazelle"
|
||||
}],
|
||||
"SA342M": [{
|
||||
"default": "SA 342M Gazelle",
|
||||
"UK": "Gazelle AH.1"
|
||||
}],
|
||||
"SA342Mistral": [{
|
||||
"default": "SA 342M Gazelle Mistral"
|
||||
}],
|
||||
"SpitfireLFMkIX": [{
|
||||
"default": "Spitfire LF Mk IX"
|
||||
}],
|
||||
"SpitfireLFMkIXCW": [{
|
||||
"default": "Spitfire LF Mk IX (Clipped Wings)"
|
||||
}],
|
||||
"Su-17M4": [{
|
||||
"default": "Su-17M4 Fitter-K",
|
||||
"Poland": "Su-22M4 Fitter-K"
|
||||
}],
|
||||
"Su-24M": [{
|
||||
"default": "Su-24M Fencer-D"
|
||||
}],
|
||||
"Su-25": [{
|
||||
"default": "Su-25 Frogfoot"
|
||||
}],
|
||||
"Su-25T": [{
|
||||
"default": "Su-25T Frogfoot"
|
||||
}],
|
||||
"Su-27": [{
|
||||
"default": "Su-27 Flanker-B"
|
||||
}],
|
||||
"Su-30": [{
|
||||
"default": "Su-30 Flanker-C"
|
||||
}],
|
||||
"Su-33": [{
|
||||
"default": "Su-33 Flanker-D"
|
||||
}],
|
||||
"Su-34": [{
|
||||
"default": "Su-34 Fullback"
|
||||
}],
|
||||
"Su-57": [{
|
||||
"default": "Su-57 Felon"
|
||||
}],
|
||||
"Tornado GR4": [{
|
||||
"default": "Tornado GR4"
|
||||
}],
|
||||
"Tornado IDS": [{
|
||||
"default": "Tornado IDS"
|
||||
}],
|
||||
"Tu-22M3": [{
|
||||
"default": "Tu-22M3 Backfire-C"
|
||||
}],
|
||||
"Tu-95MS": [{
|
||||
"default": "Tu-95MS Bear-H"
|
||||
}],
|
||||
"Tu-160": [{
|
||||
"default": "Tu-160 Blackjack"
|
||||
}],
|
||||
"UH-1H": [{
|
||||
"default": "UH-1H Iroquois",
|
||||
"Germany": "UH-1D Iroquois"
|
||||
}]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user