Add custom flight names

Mildly breaks save compat with 2.3; All existing flight dialogs will be
broken, passing the turn or recreating all the flights in the UI will
allow you to continue
This commit is contained in:
walterroach 2020-12-28 10:52:25 -06:00
parent 9fd5c6f230
commit d7e48662e0
7 changed files with 74 additions and 25 deletions

View File

@ -206,7 +206,7 @@ class GroundConflictGenerator:
u = random.choice(manpads) u = random.choice(manpads)
self.mission.vehicle_group( self.mission.vehicle_group(
side, side,
namegen.next_infantry_name(side, cp, u), u, namegen.next_infantry_name(side, cp.id, u), u,
position=infantry_position, position=infantry_position,
group_size=1, group_size=1,
heading=forward_heading, heading=forward_heading,
@ -220,7 +220,7 @@ class GroundConflictGenerator:
u = random.choice(possible_infantry_units) u = random.choice(possible_infantry_units)
self.mission.vehicle_group( self.mission.vehicle_group(
side, side,
namegen.next_infantry_name(side, cp, u), u, namegen.next_infantry_name(side, cp.id, u), u,
position=infantry_position, position=infantry_position,
group_size=1, group_size=1,
heading=forward_heading, heading=forward_heading,
@ -231,7 +231,7 @@ class GroundConflictGenerator:
position = infantry_position.random_point_within(55, 5) position = infantry_position.random_point_within(55, 5)
self.mission.vehicle_group( self.mission.vehicle_group(
side, side,
namegen.next_infantry_name(side, cp, u), u, namegen.next_infantry_name(side, cp.id, u), u,
position=position, position=position,
group_size=1, group_size=1,
heading=forward_heading, heading=forward_heading,

View File

@ -137,7 +137,8 @@ class Flight:
def __init__(self, package: Package, unit_type: Type[FlyingType], def __init__(self, package: Package, unit_type: Type[FlyingType],
count: int, flight_type: FlightType, start_type: str, count: int, flight_type: FlightType, start_type: str,
departure: ControlPoint, arrival: ControlPoint, departure: ControlPoint, arrival: ControlPoint,
divert: Optional[ControlPoint]) -> None: divert: Optional[ControlPoint],
custom_name: Optional[str] = None) -> None:
self.package = package self.package = package
self.unit_type = unit_type self.unit_type = unit_type
self.count = count self.count = count
@ -151,6 +152,7 @@ class Flight:
self.start_type = start_type self.start_type = start_type
self.use_custom_loadout = False self.use_custom_loadout = False
self.client_count = 0 self.client_count = 0
self.custom_name = custom_name
# Will be replaced with a more appropriate FlightPlan by # Will be replaced with a more appropriate FlightPlan by
# FlightPlanBuilder, but an empty flight plan the flight begins with an # FlightPlanBuilder, but an empty flight plan the flight begins with an
@ -172,4 +174,6 @@ class Flight:
def __repr__(self): def __repr__(self):
name = db.unit_type_name(self.unit_type) name = db.unit_type_name(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}" return f"[{self.flight_type}] {self.count} x {name}"

View File

@ -1,12 +1,18 @@
from game import db
from gen.flights.flight import Flight
import random import random
ALPHA_MILITARY = ["Alpha","Bravo","Charlie","Delta","Echo","Foxtrot", from dcs.country import Country
"Golf","Hotel","India","Juliet","Kilo","Lima","Mike", from dcs.unittype import UnitType
"November","Oscar","Papa","Quebec","Romeo","Sierra",
"Tango","Uniform","Victor","Whisky","XRay","Yankee", from game import db
"Zulu","Zero"]
from gen.flights.flight import Flight
ALPHA_MILITARY = ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot",
"Golf", "Hotel", "India", "Juliet", "Kilo", "Lima", "Mike",
"November", "Oscar", "Papa", "Quebec", "Romeo", "Sierra",
"Tango", "Uniform", "Victor", "Whisky", "XRay", "Yankee",
"Zulu", "Zero"]
class NameGenerator: class NameGenerator:
number = 0 number = 0
@ -47,36 +53,44 @@ class NameGenerator:
def reset(self): def reset(self):
self.number = 0 self.number = 0
self.ANIMALS = NameGenerator.ANIMALS.copy() self.ANIMALS = NameGenerator.ANIMALS.copy()
def reset_numbers(self): def reset_numbers(self):
self.number = 0 self.number = 0
self.infantry_number = 0 self.infantry_number = 0
def next_aircraft_name(self, country: int, parent_base_id: int, flight: Flight): def next_aircraft_name(self, country: Country, parent_base_id: int, flight: Flight):
self.number += 1 self.number += 1
name_str = "{} {}".format(flight.package.target.name, flight.flight_type) try:
if flight.custom_name:
name_str = flight.custom_name
else:
name_str = "{} {}".format(
flight.package.target.name, flight.flight_type)
except AttributeError: # Here to maintain save compatibility with 2.3
name_str = "{} {}".format(
flight.package.target.name, flight.flight_type)
return "{}|{}|{}|{}|{}|".format(name_str, country.id, self.number, parent_base_id, db.unit_type_name(flight.unit_type)) return "{}|{}|{}|{}|{}|".format(name_str, country.id, self.number, parent_base_id, db.unit_type_name(flight.unit_type))
def next_unit_name(self, country, parent_base_id, unit_type): def next_unit_name(self, country: Country, parent_base_id: int, unit_type: UnitType):
self.number += 1 self.number += 1
return "unit|{}|{}|{}|{}|".format(country.id, self.number, parent_base_id, db.unit_type_name(unit_type)) return "unit|{}|{}|{}|{}|".format(country.id, self.number, parent_base_id, db.unit_type_name(unit_type))
def next_infantry_name(self, country, parent_base_id, unit_type): def next_infantry_name(self, country: Country, parent_base_id: int, unit_type: UnitType):
self.infantry_number += 1 self.infantry_number += 1
return "infantry|{}|{}|{}|{}|".format(country.id, self.infantry_number, parent_base_id, db.unit_type_name(unit_type)) return "infantry|{}|{}|{}|{}|".format(country.id, self.infantry_number, parent_base_id, db.unit_type_name(unit_type))
def next_basedefense_name(self): def next_basedefense_name(self):
return "basedefense_aa|0|0|" return "basedefense_aa|0|0|"
def next_awacs_name(self, country): def next_awacs_name(self, country: Country):
self.number += 1 self.number += 1
return "awacs|{}|{}|0|".format(country.id, self.number) return "awacs|{}|{}|0|".format(country.id, self.number)
def next_tanker_name(self, country, unit_type): def next_tanker_name(self, country: Country, unit_type: UnitType):
self.number += 1 self.number += 1
return "tanker|{}|{}|0|{}".format(country.id, self.number, db.unit_type_name(unit_type)) return "tanker|{}|{}|0|{}".format(country.id, self.number, db.unit_type_name(unit_type))
def next_carrier_name(self, country): def next_carrier_name(self, country: Country):
self.number += 1 self.number += 1
return "carrier|{}|{}|0|".format(country.id, self.number) return "carrier|{}|{}|0|".format(country.id, self.number)
@ -90,6 +104,3 @@ class NameGenerator:
namegen = NameGenerator() namegen = NameGenerator()

View File

@ -65,7 +65,7 @@ class FlightDelegate(QStyledItemDelegate):
name = db.unit_type_name(flight.unit_type) name = db.unit_type_name(flight.unit_type)
estimator = TotEstimator(self.package) estimator = TotEstimator(self.package)
delay = estimator.mission_start_time(flight) delay = estimator.mission_start_time(flight)
return f"[{task}] {count} x {name} in {delay}" return f"{flight} in {delay}"
def second_row_text(self, index: QModelIndex) -> str: def second_row_text(self, index: QModelIndex) -> str:
flight = self.flight(index) flight = self.flight(index)

View File

@ -1,3 +1,4 @@
from re import L
from typing import Optional from typing import Optional
from PySide2.QtCore import Qt, Signal from PySide2.QtCore import Qt, Signal
@ -6,6 +7,7 @@ from PySide2.QtWidgets import (
QMessageBox, QMessageBox,
QPushButton, QPushButton,
QVBoxLayout, QVBoxLayout,
QLineEdit,
) )
from dcs.planes import PlaneType from dcs.planes import PlaneType
@ -31,6 +33,7 @@ class QFlightCreator(QDialog):
self.game = game self.game = game
self.package = package self.package = package
self.custom_name_text = None
self.setWindowTitle("Create flight") self.setWindowTitle("Create flight")
self.setWindowIcon(EVENT_ICONS["strike"]) self.setWindowIcon(EVENT_ICONS["strike"])
@ -88,6 +91,12 @@ class QFlightCreator(QDialog):
layout.addLayout( layout.addLayout(
QLabeledWidget("Client Slots:", self.client_slots_spinner)) QLabeledWidget("Client Slots:", self.client_slots_spinner))
self.custom_name = QLineEdit()
self.custom_name.textChanged.connect(self.set_custom_name_text)
layout.addLayout(
QLabeledWidget("Custom Flight Name (Optional)", self.custom_name)
)
layout.addStretch() layout.addStretch()
self.create_button = QPushButton("Create") self.create_button = QPushButton("Create")
@ -96,6 +105,9 @@ class QFlightCreator(QDialog):
self.setLayout(layout) self.setLayout(layout)
def set_custom_name_text(self, text: str):
self.custom_name_text = text
def verify_form(self) -> Optional[str]: def verify_form(self) -> Optional[str]:
aircraft: PlaneType = self.aircraft_selector.currentData() aircraft: PlaneType = self.aircraft_selector.currentData()
origin: ControlPoint = self.departure.currentData() origin: ControlPoint = self.departure.currentData()
@ -115,6 +127,8 @@ class QFlightCreator(QDialog):
return f"{origin.name} has only {available} {aircraft.id} available." return f"{origin.name} has only {available} {aircraft.id} available."
if size <= 0: if size <= 0:
return f"Flight must have at least one aircraft." return f"Flight must have at least one aircraft."
if self.custom_name_text and "|" in self.custom_name_text:
return f"Cannot include | in flight name"
return None return None
def create_flight(self) -> None: def create_flight(self) -> None:
@ -141,7 +155,7 @@ class QFlightCreator(QDialog):
else: else:
start_type = "Warm" start_type = "Warm"
flight = Flight(self.package, aircraft, size, task, start_type, origin, flight = Flight(self.package, aircraft, size, task, start_type, origin,
arrival, divert) arrival, divert, custom_name=self.custom_name_text)
flight.client_count = self.client_slots_spinner.value() flight.client_count = self.client_slots_spinner.value()
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences

View File

@ -0,0 +1,16 @@
from PySide2.QtWidgets import QGroupBox, QHBoxLayout, QLabel
from gen.flights.flight import Flight
class QFlightCustomName(QGroupBox):
def __init__(self, flight: Flight):
super(QFlightCustomName, self).__init__()
self.flight = flight
self.layout = QHBoxLayout()
self.custom_name_label = QLabel(f"Custom Name: {flight.custom_name}")
self.layout.addWidget(self.custom_name_label)
self.setLayout(self.layout)

View File

@ -1,5 +1,5 @@
from PySide2.QtCore import Signal from PySide2.QtCore import Signal
from PySide2.QtWidgets import QFrame, QGridLayout, QVBoxLayout from PySide2.QtWidgets import QFrame, QGridLayout, QVBoxLayout, QLabel
from game import Game from game import Game
from gen.ato import Package from gen.ato import Package
@ -12,6 +12,8 @@ from qt_ui.windows.mission.flight.settings.QFlightStartType import \
QFlightStartType QFlightStartType
from qt_ui.windows.mission.flight.settings.QFlightTypeTaskInfo import \ from qt_ui.windows.mission.flight.settings.QFlightTypeTaskInfo import \
QFlightTypeTaskInfo QFlightTypeTaskInfo
from qt_ui.windows.mission.flight.settings.QCustomName import \
QFlightCustomName
class QGeneralFlightSettingsTab(QFrame): class QGeneralFlightSettingsTab(QFrame):
@ -25,10 +27,12 @@ class QGeneralFlightSettingsTab(QFrame):
flight_departure = QFlightDepartureDisplay(package, flight) flight_departure = QFlightDepartureDisplay(package, flight)
flight_slots = QFlightSlotEditor(flight, game) flight_slots = QFlightSlotEditor(flight, game)
flight_start_type = QFlightStartType(flight) flight_start_type = QFlightStartType(flight)
flight_custom_name = QFlightCustomName(flight)
layout.addWidget(flight_info, 0, 0) layout.addWidget(flight_info, 0, 0)
layout.addWidget(flight_departure, 1, 0) layout.addWidget(flight_departure, 1, 0)
layout.addWidget(flight_slots, 2, 0) layout.addWidget(flight_slots, 2, 0)
layout.addWidget(flight_start_type, 3, 0) layout.addWidget(flight_start_type, 3, 0)
layout.addWidget(flight_custom_name, 4, 0)
vstretch = QVBoxLayout() vstretch = QVBoxLayout()
vstretch.addStretch() vstretch.addStretch()
layout.addLayout(vstretch, 3, 0) layout.addLayout(vstretch, 3, 0)