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
@dataclass
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):
# Generator settings
self.inverted = False
self.do_not_generate_carrier = False # TODO : implement
self.do_not_generate_lha = False # TODO : implement
self.do_not_generate_player_navy = True # TODO : implement
self.do_not_generate_enemy_navy = True # TODO : implement
# Difficulty settings
player_skill: str = "Good"
enemy_skill: str = "Average"
enemy_vehicle_skill: str = "Average"
map_coalition_visibility: str = "All Units"
labels: str = "Full"
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
self.player_skill = "Good"
self.enemy_skill = "Average"
self.enemy_vehicle_skill = "Average"
self.map_coalition_visibility = "All Units"
self.labels = "Full"
self.only_player_takeoff = True # Legacy parameter do not use
self.night_disabled = False
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
perf_red_alert_state: bool = True
perf_smoke_gen: bool = True
perf_artillery: bool = True
perf_moving_units: bool = True
perf_infantry: bool = True
perf_ai_parking_start: bool = True
perf_destroyed_units: bool = True
# Performance oriented
self.perf_red_alert_state = True
self.perf_smoke_gen = True
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
perf_culling: bool = False
perf_culling_distance: int = 100
# Performance culling
self.perf_culling = False
self.perf_culling_distance = 100
# LUA Plugins system
plugins: Dict[str, bool] = field(default_factory=dict)
# LUA Plugins system
self.plugins: Dict[str, bool] = {}
# Cheating
show_red_ato: bool = False
# Cheating
self.show_red_ato = False
self.never_delay_player_flights = False
never_delay_player_flights: bool = False
@staticmethod
def plugin_settings_key(identifier: str) -> str:

View File

@ -1,13 +1,19 @@
import argparse
import logging
import os
import sys
from datetime import datetime
from pathlib import Path
from typing import Optional
import dcs
from PySide2 import QtWidgets
from PySide2.QtGui import QPixmap
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 (
liberation_install,
liberation_theme,
@ -16,36 +22,30 @@ from qt_ui import (
)
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
from qt_ui.windows.QLiberationWindow import QLiberationWindow
from qt_ui.windows.newgame.QCampaignList import Campaign
from qt_ui.windows.preferences.QLiberationFirstStartWindow import \
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
app = QApplication(sys.argv)
# init the theme and load the stylesheet based on the theme index
liberation_theme.init()
css = ""
with open("./resources/stylesheets/"+liberation_theme.get_theme_css_file()) as stylesheet:
app.setStyleSheet(stylesheet.read())
# Inject custom payload in pydcs framework
custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..\\resources\\customized_payloads")
if os.path.exists(custom_payloads):
dcs.planes.FlyingType.payload_dirs.append(custom_payloads)
dcs.unittype.FlyingType.payload_dirs.append(custom_payloads)
else:
# For release version the path is different.
custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)),
"resources\\customized_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()
if first_start:
@ -79,7 +79,7 @@ if __name__ == "__main__":
GameUpdateSignal()
# Start window
window = QLiberationWindow()
window = QLiberationWindow(game)
window.showMaximized()
splash.finish(window)
qt_execution_code = app.exec_()
@ -91,3 +91,65 @@ if __name__ == "__main__":
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
its ATO objects.
"""
def __init__(self) -> None:
self.game: Optional[Game] = None
self.ato_model = AtoModel(self.game, AirTaskingOrder())
self.red_ato_model = AtoModel(self.game, AirTaskingOrder())
def __init__(self, game: Optional[Game]) -> None:
self.game: Optional[Game] = game
if self.game is None:
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:
"""Updates the managed Game object.

View File

@ -35,11 +35,11 @@ from qt_ui.windows.preferences.QLiberationPreferencesWindow import \
class QLiberationWindow(QMainWindow):
def __init__(self):
def __init__(self, game: Optional[Game]) -> None:
super(QLiberationWindow, self).__init__()
self.game: Optional[Game] = None
self.game_model = GameModel()
self.game = game
self.game_model = GameModel(game)
Dialog.set_game(self.game_model)
self.ato_panel = QAirTaskingOrderPanel(self.game_model)
self.info_panel = QInfoPanel(self.game)
@ -60,7 +60,10 @@ class QLiberationWindow(QMainWindow):
self.setGeometry(0, 0, screen.width(), screen.height())
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):
hbox = QSplitter(Qt.Horizontal)

View File

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