from __future__ import unicode_literals import logging from typing import List, Optional from PySide2 import QtGui, QtWidgets from PySide2.QtCore import QItemSelectionModel, QPoint, Qt from PySide2.QtWidgets import QVBoxLayout, QTextEdit from jinja2 import Environment, FileSystemLoader, select_autoescape from game import db from game.settings import Settings from qt_ui.widgets.spinsliders import TenthsSpinSlider from qt_ui.windows.newgame.QCampaignList import ( Campaign, QCampaignList, load_campaigns, ) from game.theater.start_generator import GameGenerator, GeneratorSettings jinja_env = Environment( loader=FileSystemLoader("resources/ui/templates"), autoescape=select_autoescape( disabled_extensions=("",), default_for_string=True, default=True, ), trim_blocks=True, lstrip_blocks=True, ) DEFAULT_BUDGET = 1600 class NewGameWizard(QtWidgets.QWizard): def __init__(self, parent=None): super(NewGameWizard, self).__init__(parent) self.campaigns = load_campaigns() self.addPage(IntroPage()) self.addPage(FactionSelection()) self.addPage(TheaterConfiguration(self.campaigns)) self.addPage(GeneratorOptions()) self.addPage(DifficultyAndAutomationOptions()) self.addPage(ConclusionPage()) self.setPixmap(QtWidgets.QWizard.WatermarkPixmap, QtGui.QPixmap('./resources/ui/wizard/watermark1.png')) self.setWizardStyle(QtWidgets.QWizard.ModernStyle) self.setWindowTitle("New Game") self.generatedGame = None def accept(self): logging.info("New Game Wizard accept") logging.info("======================") campaign = self.field("selectedCampaign") if campaign is None: campaign = self.campaigns[0] settings = Settings( player_income_multiplier=self.field( "player_income_multiplier") / 10, enemy_income_multiplier=self.field("enemy_income_multiplier") / 10, automate_runway_repair=self.field("automate_runway_repairs"), automate_front_line_reinforcements=self.field( "automate_front_line_purchases" ), automate_aircraft_reinforcements=self.field( "automate_aircraft_purchases" ), supercarrier=self.field("supercarrier") ) generator_settings = GeneratorSettings( start_date=db.TIME_PERIODS[ list(db.TIME_PERIODS.keys())[self.field("timePeriod")]], player_budget=int(self.field("starting_money")), enemy_budget=int(self.field("enemy_starting_money")), # QSlider forces integers, so we use 1 to 50 and divide by 10 to # give 0.1 to 5.0. midgame=self.field("midGame"), inverted=self.field("invertMap"), no_carrier=self.field("no_carrier"), no_lha=self.field("no_lha"), no_player_navy=self.field("no_player_navy"), no_enemy_navy=self.field("no_enemy_navy") ) blue_faction = [c for c in db.FACTIONS][self.field("blueFaction")] red_faction = [c for c in db.FACTIONS][self.field("redFaction")] generator = GameGenerator( blue_faction, red_faction, campaign.load_theater(), settings, generator_settings ) self.generatedGame = generator.generate() super(NewGameWizard, self).accept() class IntroPage(QtWidgets.QWizardPage): def __init__(self, parent=None): super(IntroPage, self).__init__(parent) self.setTitle("Introduction") self.setPixmap(QtWidgets.QWizard.WatermarkPixmap, QtGui.QPixmap('./resources/ui/wizard/watermark1.png')) label = QtWidgets.QLabel("This wizard will help you setup a new game.\n\n" "Please make sure you saved and backed up your previous game before going through.") label.setWordWrap(True) layout = QtWidgets.QVBoxLayout() layout.addWidget(label) self.setLayout(layout) class FactionSelection(QtWidgets.QWizardPage): def __init__(self, parent=None): super(FactionSelection, self).__init__(parent) self.setTitle("Faction selection") self.setSubTitle("\nChoose the two opposing factions and select the player side.") self.setPixmap(QtWidgets.QWizard.LogoPixmap, QtGui.QPixmap('./resources/ui/misc/generator.png')) self.setMinimumHeight(250) # Factions selection self.factionsGroup = QtWidgets.QGroupBox("Factions") self.factionsGroupLayout = QtWidgets.QHBoxLayout() self.blueGroupLayout = QtWidgets.QGridLayout() self.redGroupLayout = QtWidgets.QGridLayout() blueFaction = QtWidgets.QLabel("Player Faction :") self.blueFactionSelect = QtWidgets.QComboBox() for f in db.FACTIONS: self.blueFactionSelect.addItem(f) blueFaction.setBuddy(self.blueFactionSelect) redFaction = QtWidgets.QLabel("Enemy Faction :") self.redFactionSelect = QtWidgets.QComboBox() redFaction.setBuddy(self.redFactionSelect) # Faction description self.blueFactionDescription = QTextEdit("") self.blueFactionDescription.setReadOnly(True) self.redFactionDescription = QTextEdit("") self.redFactionDescription.setReadOnly(True) # Setup default selected factions for i, r in enumerate(db.FACTIONS): self.redFactionSelect.addItem(r) if r == "Russia 1990": self.redFactionSelect.setCurrentIndex(i) if r == "USA 2005": self.blueFactionSelect.setCurrentIndex(i) self.blueGroupLayout.addWidget(blueFaction, 0, 0) self.blueGroupLayout.addWidget(self.blueFactionSelect, 0, 1) self.blueGroupLayout.addWidget(self.blueFactionDescription, 1, 0, 1, 2) self.redGroupLayout.addWidget(redFaction, 0, 0) self.redGroupLayout.addWidget(self.redFactionSelect, 0, 1) self.redGroupLayout.addWidget(self.redFactionDescription, 1, 0, 1, 2) self.factionsGroupLayout.addLayout(self.blueGroupLayout) self.factionsGroupLayout.addLayout(self.redGroupLayout) self.factionsGroup.setLayout(self.factionsGroupLayout) # Create required mod layout self.requiredModsGroup = QtWidgets.QGroupBox("Required Mods") self.requiredModsGroupLayout = QtWidgets.QHBoxLayout() self.requiredMods = QtWidgets.QLabel("") self.requiredModsGroupLayout.addWidget(self.requiredMods) self.requiredModsGroup.setLayout(self.requiredModsGroupLayout) # Link form fields self.registerField('blueFaction', self.blueFactionSelect) self.registerField('redFaction', self.redFactionSelect) # Build layout layout = QtWidgets.QVBoxLayout() layout.addWidget(self.factionsGroup) layout.addWidget(self.requiredModsGroup) self.setLayout(layout) self.updateUnitRecap() self.blueFactionSelect.activated.connect(self.updateUnitRecap) self.redFactionSelect.activated.connect(self.updateUnitRecap) def updateUnitRecap(self): red_faction = db.FACTIONS[self.redFactionSelect.currentText()] blue_faction = db.FACTIONS[self.blueFactionSelect.currentText()] template = jinja_env.get_template("factiontemplate_EN.j2") blue_faction_txt = template.render({"faction": blue_faction}) red_faction_txt = template.render({"faction": red_faction}) self.blueFactionDescription.setText(blue_faction_txt) self.redFactionDescription.setText(red_faction_txt) # Compute mod requirements txt self.requiredMods.setText("\n\n") else: self.requiredMods.setText(self.requiredMods.text() + "
  • None
  • \n") class TheaterConfiguration(QtWidgets.QWizardPage): def __init__(self, campaigns: List[Campaign], parent=None) -> None: super().__init__(parent) self.setTitle("Theater configuration") self.setSubTitle("\nChoose a terrain and time period for this game.") self.setPixmap(QtWidgets.QWizard.LogoPixmap, QtGui.QPixmap('./resources/ui/wizard/logo1.png')) self.setPixmap(QtWidgets.QWizard.WatermarkPixmap, QtGui.QPixmap('./resources/ui/wizard/watermark3.png')) # List of campaigns campaignList = QCampaignList(campaigns) self.registerField("selectedCampaign", campaignList) # Faction description self.campaignMapDescription = QTextEdit("") self.campaignMapDescription.setReadOnly(True) def on_campaign_selected(): template = jinja_env.get_template("campaigntemplate_EN.j2") index = campaignList.selectionModel().currentIndex().row() campaign = campaignList.campaigns[index] self.setField("selectedCampaign", campaign) self.campaignMapDescription.setText(template.render({"campaign": campaign})) campaignList.selectionModel().setCurrentIndex(campaignList.indexAt(QPoint(1, 1)), QItemSelectionModel.Rows) campaignList.selectionModel().selectionChanged.connect(on_campaign_selected) on_campaign_selected() # Campaign settings mapSettingsGroup = QtWidgets.QGroupBox("Map Settings") invertMap = QtWidgets.QCheckBox() self.registerField('invertMap', invertMap) mapSettingsLayout = QtWidgets.QGridLayout() mapSettingsLayout.addWidget(QtWidgets.QLabel("Invert Map"), 0, 0) mapSettingsLayout.addWidget(invertMap, 0, 1) mapSettingsLayout.addWidget(QtWidgets.QLabel("Start at mid game"), 1, 0) midgame = QtWidgets.QCheckBox() self.registerField('midGame', midgame) mapSettingsLayout.addWidget(midgame, 1, 1) mapSettingsGroup.setLayout(mapSettingsLayout) # Time Period timeGroup = QtWidgets.QGroupBox("Time Period") timePeriod = QtWidgets.QLabel("Start date :") timePeriodSelect = QtWidgets.QComboBox() for r in db.TIME_PERIODS: timePeriodSelect.addItem(r) timePeriod.setBuddy(timePeriodSelect) timePeriodSelect.setCurrentIndex(21) # Register fields self.registerField('timePeriod', timePeriodSelect) self.registerField('timePeriod', timePeriodSelect) timeGroupLayout = QtWidgets.QGridLayout() timeGroupLayout.addWidget(timePeriod, 0, 0) timeGroupLayout.addWidget(timePeriodSelect, 0, 1) timeGroup.setLayout(timeGroupLayout) layout = QtWidgets.QGridLayout() layout.setColumnMinimumWidth(0, 20) layout.addWidget(campaignList, 0, 0, 3, 1) layout.addWidget(self.campaignMapDescription, 0, 1, 1, 1) layout.addWidget(mapSettingsGroup, 1, 1, 1, 1) layout.addWidget(timeGroup, 2, 1, 1, 1) self.setLayout(layout) class CurrencySpinner(QtWidgets.QSpinBox): def __init__(self, minimum: Optional[int] = None, maximum: Optional[int] = None, initial: Optional[int] = None) -> None: super().__init__() if minimum is not None: self.setMinimum(minimum) if maximum is not None: self.setMaximum(maximum) if initial is not None: self.setValue(initial) def textFromValue(self, val: int) -> str: return f"${val}" class BudgetInputs(QtWidgets.QGridLayout): def __init__(self, label: str) -> None: super().__init__() self.addWidget(QtWidgets.QLabel(label), 0, 0) minimum = 0 maximum = 5000 initial = DEFAULT_BUDGET slider = QtWidgets.QSlider(Qt.Horizontal) slider.setMinimum(minimum) slider.setMaximum(maximum) slider.setValue(initial) self.starting_money = CurrencySpinner(minimum, maximum, initial) slider.valueChanged.connect(lambda x: self.starting_money.setValue(x)) self.starting_money.valueChanged.connect(lambda x: slider.setValue(x)) self.addWidget(slider, 1, 0) self.addWidget(self.starting_money, 1, 1) class DifficultyAndAutomationOptions(QtWidgets.QWizardPage): def __init__(self, parent=None) -> None: super().__init__(parent) self.setTitle("Difficulty and automation options") self.setSubTitle("\nOptions controlling game difficulty and level of " "player involvement.") self.setPixmap(QtWidgets.QWizard.LogoPixmap, QtGui.QPixmap('./resources/ui/wizard/logo1.png')) layout = QtWidgets.QVBoxLayout() economy_group = QtWidgets.QGroupBox("Economy options") layout.addWidget(economy_group) economy_layout = QtWidgets.QVBoxLayout() economy_group.setLayout(economy_layout) player_income = TenthsSpinSlider("Player income multiplier", 1, 50, 10) self.registerField("player_income_multiplier", player_income.spinner) economy_layout.addLayout(player_income) enemy_income = TenthsSpinSlider("Enemy income multiplier", 1, 50, 10) self.registerField("enemy_income_multiplier", enemy_income.spinner) economy_layout.addLayout(enemy_income) player_budget = BudgetInputs("Player starting budget") self.registerField('starting_money', player_budget.starting_money) economy_layout.addLayout(player_budget) enemy_budget = BudgetInputs("Enemy starting budget") self.registerField("enemy_starting_money", enemy_budget.starting_money) economy_layout.addLayout(enemy_budget) assist_group = QtWidgets.QGroupBox("Player assists") layout.addWidget(assist_group) assist_layout = QtWidgets.QGridLayout() assist_group.setLayout(assist_layout) assist_layout.addWidget( QtWidgets.QLabel("Automate runway repairs"), 0, 0) runway_repairs = QtWidgets.QCheckBox() self.registerField("automate_runway_repairs", runway_repairs) assist_layout.addWidget(runway_repairs, 0, 1, Qt.AlignRight) assist_layout.addWidget( QtWidgets.QLabel("Automate front-line purchases"), 1, 0) front_line = QtWidgets.QCheckBox() self.registerField("automate_front_line_purchases", front_line) assist_layout.addWidget(front_line, 1, 1, Qt.AlignRight) assist_layout.addWidget( QtWidgets.QLabel("Automate aircraft purchases"), 2, 0) aircraft = QtWidgets.QCheckBox() self.registerField("automate_aircraft_purchases", aircraft) assist_layout.addWidget(aircraft, 2, 1, Qt.AlignRight) self.setLayout(layout) class GeneratorOptions(QtWidgets.QWizardPage): def __init__(self, parent=None): super().__init__(parent) self.setTitle("Generator settings") self.setSubTitle("\nOptions affecting the generation of the game.") self.setPixmap(QtWidgets.QWizard.LogoPixmap, QtGui.QPixmap('./resources/ui/wizard/logo1.png')) # Campaign settings generatorSettingsGroup = QtWidgets.QGroupBox("Generator Settings") no_carrier = QtWidgets.QCheckBox() self.registerField('no_carrier', no_carrier) no_lha = QtWidgets.QCheckBox() self.registerField('no_lha', no_lha) supercarrier = QtWidgets.QCheckBox() self.registerField('supercarrier', supercarrier) no_player_navy = QtWidgets.QCheckBox() self.registerField('no_player_navy', no_player_navy) no_enemy_navy = QtWidgets.QCheckBox() self.registerField('no_enemy_navy', no_enemy_navy) generatorLayout = QtWidgets.QGridLayout() generatorLayout.addWidget(QtWidgets.QLabel("No Aircraft Carriers"), 1, 0) generatorLayout.addWidget(no_carrier, 1, 1) generatorLayout.addWidget(QtWidgets.QLabel("No LHA"), 2, 0) generatorLayout.addWidget(no_lha, 2, 1) generatorLayout.addWidget(QtWidgets.QLabel("Use Supercarrier module"), 3, 0) generatorLayout.addWidget(supercarrier, 3, 1) generatorLayout.addWidget(QtWidgets.QLabel("No Player Navy"), 4, 0) generatorLayout.addWidget(no_player_navy, 4, 1) generatorLayout.addWidget(QtWidgets.QLabel("No Enemy Navy"), 5, 0) generatorLayout.addWidget(no_enemy_navy, 5, 1) generatorSettingsGroup.setLayout(generatorLayout) mlayout = QVBoxLayout() mlayout.addWidget(generatorSettingsGroup) self.setLayout(mlayout) class ConclusionPage(QtWidgets.QWizardPage): def __init__(self, parent=None): super(ConclusionPage, self).__init__(parent) self.setTitle("Conclusion") self.setSubTitle("\n\n") self.setPixmap(QtWidgets.QWizard.WatermarkPixmap, QtGui.QPixmap('./resources/ui/wizard/watermark2.png')) self.label = QtWidgets.QLabel("Click 'Finish' to generate and start the new game.") self.label.setWordWrap(True) layout = QtWidgets.QVBoxLayout() layout.addWidget(self.label) self.setLayout(layout)