mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Merge remote-tracking branch 'khopa/develop' into develop
This commit is contained in:
commit
1843d23203
@ -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