Add command line option to generate a new game.

Saves us a ton of clicks while developing the campaign generator.
This commit is contained in:
Dan Albert 2020-11-17 18:56:35 -08:00
parent 8345063e84
commit 1f12546ff4
5 changed files with 136 additions and 66 deletions

View File

@ -1,52 +1,52 @@
from dataclasses import dataclass, field
from typing import Dict from typing import Dict
@dataclass
class Settings: class Settings:
# Generator settings
inverted: bool = False
do_not_generate_carrier: bool = False # TODO : implement
do_not_generate_lha: bool = False # TODO : implement
do_not_generate_player_navy: bool = True # TODO : implement
do_not_generate_enemy_navy: bool = True # TODO : implement
def __init__(self): # Difficulty settings
# Generator settings player_skill: str = "Good"
self.inverted = False enemy_skill: str = "Average"
self.do_not_generate_carrier = False # TODO : implement enemy_vehicle_skill: str = "Average"
self.do_not_generate_lha = False # TODO : implement map_coalition_visibility: str = "All Units"
self.do_not_generate_player_navy = True # TODO : implement labels: str = "Full"
self.do_not_generate_enemy_navy = True # TODO : implement only_player_takeoff: bool = True # Legacy parameter do not use
night_disabled: bool = False
external_views_allowed: bool = True
supercarrier: bool = False
multiplier: bool = 1
generate_marks: bool = True
sams: bool = True # Legacy parameter do not use
cold_start: bool = False # Legacy parameter do not use
version: bool = None
# Difficulty settings # Performance oriented
self.player_skill = "Good" perf_red_alert_state: bool = True
self.enemy_skill = "Average" perf_smoke_gen: bool = True
self.enemy_vehicle_skill = "Average" perf_artillery: bool = True
self.map_coalition_visibility = "All Units" perf_moving_units: bool = True
self.labels = "Full" perf_infantry: bool = True
self.only_player_takeoff = True # Legacy parameter do not use perf_ai_parking_start: bool = True
self.night_disabled = False perf_destroyed_units: bool = True
self.external_views_allowed = True
self.supercarrier = False
self.multiplier = 1
self.generate_marks = True
self.sams = True # Legacy parameter do not use
self.cold_start = False # Legacy parameter do not use
self.version = None
# Performance oriented # Performance culling
self.perf_red_alert_state = True perf_culling: bool = False
self.perf_smoke_gen = True perf_culling_distance: int = 100
self.perf_artillery = True
self.perf_moving_units = True
self.perf_infantry = True
self.perf_ai_parking_start = True
self.perf_destroyed_units = True
# Performance culling # LUA Plugins system
self.perf_culling = False plugins: Dict[str, bool] = field(default_factory=dict)
self.perf_culling_distance = 100
# LUA Plugins system # Cheating
self.plugins: Dict[str, bool] = {} show_red_ato: bool = False
# Cheating never_delay_player_flights: bool = False
self.show_red_ato = False
self.never_delay_player_flights = False
@staticmethod @staticmethod
def plugin_settings_key(identifier: str) -> str: def plugin_settings_key(identifier: str) -> str:

View File

@ -1,13 +1,19 @@
import argparse
import logging import logging
import os import os
import sys import sys
from datetime import datetime
from pathlib import Path
from typing import Optional
import dcs import dcs
from PySide2 import QtWidgets from PySide2 import QtWidgets
from PySide2.QtGui import QPixmap from PySide2.QtGui import QPixmap
from PySide2.QtWidgets import QApplication, QSplashScreen from PySide2.QtWidgets import QApplication, QSplashScreen
from game import db, persistency, VERSION from game import Game, db, persistency, VERSION
from game.settings import Settings
from game.theater.start_generator import GameGenerator
from qt_ui import ( from qt_ui import (
liberation_install, liberation_install,
liberation_theme, liberation_theme,
@ -16,36 +22,30 @@ from qt_ui import (
) )
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
from qt_ui.windows.QLiberationWindow import QLiberationWindow from qt_ui.windows.QLiberationWindow import QLiberationWindow
from qt_ui.windows.newgame.QCampaignList import Campaign
from qt_ui.windows.preferences.QLiberationFirstStartWindow import \ from qt_ui.windows.preferences.QLiberationFirstStartWindow import \
QLiberationFirstStartWindow QLiberationFirstStartWindow
# Logging setup
logging_config.init_logging(VERSION)
if __name__ == "__main__":
# Load eagerly to catch errors early.
db.FACTIONS.initialize()
def run_ui(game: Optional[Game] = None) -> None:
os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" # Potential fix for 4K screens os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" # Potential fix for 4K screens
app = QApplication(sys.argv) app = QApplication(sys.argv)
# init the theme and load the stylesheet based on the theme index # init the theme and load the stylesheet based on the theme index
liberation_theme.init() liberation_theme.init()
css = ""
with open("./resources/stylesheets/"+liberation_theme.get_theme_css_file()) as stylesheet: with open("./resources/stylesheets/"+liberation_theme.get_theme_css_file()) as stylesheet:
app.setStyleSheet(stylesheet.read()) app.setStyleSheet(stylesheet.read())
# Inject custom payload in pydcs framework # Inject custom payload in pydcs framework
custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..\\resources\\customized_payloads") custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..\\resources\\customized_payloads")
if os.path.exists(custom_payloads): if os.path.exists(custom_payloads):
dcs.planes.FlyingType.payload_dirs.append(custom_payloads) dcs.unittype.FlyingType.payload_dirs.append(custom_payloads)
else: else:
# For release version the path is different. # For release version the path is different.
custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)), custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)),
"resources\\customized_payloads") "resources\\customized_payloads")
if os.path.exists(custom_payloads): if os.path.exists(custom_payloads):
dcs.planes.FlyingType.payload_dirs.append(custom_payloads) dcs.unittype.FlyingType.payload_dirs.append(custom_payloads)
first_start = liberation_install.init() first_start = liberation_install.init()
if first_start: if first_start:
@ -79,7 +79,7 @@ if __name__ == "__main__":
GameUpdateSignal() GameUpdateSignal()
# Start window # Start window
window = QLiberationWindow() window = QLiberationWindow(game)
window.showMaximized() window.showMaximized()
splash.finish(window) splash.finish(window)
qt_execution_code = app.exec_() qt_execution_code = app.exec_()
@ -91,3 +91,65 @@ if __name__ == "__main__":
logging.info("QT process exited with code : " + str(qt_execution_code)) logging.info("QT process exited with code : " + str(qt_execution_code))
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest="subcommand")
def path_arg(arg: str) -> Path:
path = Path(arg)
if not path.exists():
raise argparse.ArgumentTypeError("path does not exist")
return path
new_game = subparsers.add_parser("new-game")
new_game.add_argument(
"campaign", type=path_arg,
help="Path to the campaign to start."
)
new_game.add_argument(
"--blue", default="USA 2005", help="Name of the blue faction."
)
new_game.add_argument(
"--red", default="Russia 1990", help="Name of the red faction."
)
new_game.add_argument(
"--supercarrier", action="store_true",
help="Use the supercarrier module."
)
return parser.parse_args()
def create_game(campaign_path: Path, blue: str, red: str,
supercarrier: bool) -> Game:
campaign = Campaign.from_json(campaign_path)
generator = GameGenerator(blue, red, campaign.theater,
Settings(supercarrier=supercarrier),
start_date=datetime.today(),
starting_budget=650,
multiplier=1, midgame=False)
return generator.generate()
def main():
logging_config.init_logging(VERSION)
# Load eagerly to catch errors early.
db.FACTIONS.initialize()
game: Optional[Game] = None
args = parse_args()
if args.subcommand == "new-game":
game = create_game(args.campaign, args.blue, args.red,
args.supercarrier)
run_ui(game)
if __name__ == "__main__":
main()

View File

@ -277,10 +277,14 @@ class GameModel:
This isn't a real Qt data model, but simplifies management of the game and This isn't a real Qt data model, but simplifies management of the game and
its ATO objects. its ATO objects.
""" """
def __init__(self) -> None: def __init__(self, game: Optional[Game]) -> None:
self.game: Optional[Game] = None self.game: Optional[Game] = game
self.ato_model = AtoModel(self.game, AirTaskingOrder()) if self.game is None:
self.red_ato_model = AtoModel(self.game, AirTaskingOrder()) self.ato_model = AtoModel(self.game, AirTaskingOrder())
self.red_ato_model = AtoModel(self.game, AirTaskingOrder())
else:
self.ato_model = AtoModel(self.game, self.game.blue_ato)
self.red_ato_model = AtoModel(self.game, self.game.red_ato)
def set(self, game: Optional[Game]) -> None: def set(self, game: Optional[Game]) -> None:
"""Updates the managed Game object. """Updates the managed Game object.

View File

@ -35,11 +35,11 @@ from qt_ui.windows.preferences.QLiberationPreferencesWindow import \
class QLiberationWindow(QMainWindow): class QLiberationWindow(QMainWindow):
def __init__(self): def __init__(self, game: Optional[Game]) -> None:
super(QLiberationWindow, self).__init__() super(QLiberationWindow, self).__init__()
self.game: Optional[Game] = None self.game = game
self.game_model = GameModel() self.game_model = GameModel(game)
Dialog.set_game(self.game_model) Dialog.set_game(self.game_model)
self.ato_panel = QAirTaskingOrderPanel(self.game_model) self.ato_panel = QAirTaskingOrderPanel(self.game_model)
self.info_panel = QInfoPanel(self.game) self.info_panel = QInfoPanel(self.game)
@ -60,7 +60,10 @@ class QLiberationWindow(QMainWindow):
self.setGeometry(0, 0, screen.width(), screen.height()) self.setGeometry(0, 0, screen.width(), screen.height())
self.setWindowState(Qt.WindowMaximized) self.setWindowState(Qt.WindowMaximized)
self.onGameGenerated(persistency.restore_game()) if self.game is None:
self.onGameGenerated(persistency.restore_game())
else:
self.onGameGenerated(self.game)
def initUi(self): def initUi(self):
hbox = QSplitter(Qt.Horizontal) hbox = QSplitter(Qt.Horizontal)

View File

@ -74,13 +74,14 @@ class NewGameWizard(QtWidgets.QWizard):
player_name = blueFaction player_name = blueFaction
enemy_name = redFaction enemy_name = redFaction
settings = Settings() settings = Settings(
settings.inverted = invertMap inverted=invertMap,
settings.supercarrier = supercarrier supercarrier=supercarrier,
settings.do_not_generate_carrier = no_carrier do_not_generate_carrier=no_carrier,
settings.do_not_generate_lha = no_lha do_not_generate_lha=no_lha,
settings.do_not_generate_player_navy = no_player_navy do_not_generate_player_navy=no_player_navy,
settings.do_not_generate_enemy_navy = no_enemy_navy do_not_generate_enemy_navy=no_enemy_navy
)
generator = GameGenerator(player_name, enemy_name, conflictTheater, generator = GameGenerator(player_name, enemy_name, conflictTheater,
settings, timePeriod, starting_money, settings, timePeriod, starting_money,