Reuse the settings screen in NewGameWizard

Resolves #123
This commit is contained in:
Raffson 2023-05-27 21:48:30 +02:00
parent 0923add514
commit 4898cdb614
No known key found for this signature in database
GPG Key ID: B0402B2C9B764D99
11 changed files with 231 additions and 170 deletions

View File

@ -14,6 +14,7 @@
* **[Modding]** Support for SW mod v2.55
* **[Modding]** Support for Spanish & Australian Naval Assets v3.2.0 by desdemicabina
* **[Modding]** Support for Iron Dome v1.2 by IDF Mods Project
* **[NewGameWizard]** Re-organized generator options & show the regular settings menu instead of the limited "Difficulty & Automation" page.
## Fixes
* **[New Game Wizard]** Settings would not persist when going back to a previous page.

View File

@ -0,0 +1,5 @@
from game.settings import Settings
class SettingsContainer:
settings: Settings

View File

@ -257,7 +257,10 @@ class Settings:
CAMPAIGN_MANAGEMENT_PAGE,
PILOTS_AND_SQUADRONS_SECTION,
default=False,
detail="If set, squadrons will be limited to a maximum number of aircraft.",
detail=(
"If set, squadrons will not be able to exceed a maximum number of aircraft "
"(configurable), and the campaign will begin with all squadrons at full strength."
),
)
# HQ Automation
@ -718,6 +721,9 @@ class Settings:
new_state = Settings().__dict__
new_state.update(state)
self.__dict__.update(new_state)
from game.plugins import LuaPluginManager
LuaPluginManager().load_settings(self)
@classmethod
def _field_description(cls, settings_field: Field[Any]) -> OptionDescription:

View File

@ -1,20 +1,20 @@
from __future__ import unicode_literals
import logging
from datetime import timedelta
from PySide2 import QtGui, QtWidgets
from game.campaignloader.campaign import Campaign
from game.dcs.aircrafttype import AircraftType
from game.settings import Settings
from game.theater.start_generator import GameGenerator, GeneratorSettings, ModSettings
from qt_ui.windows.AirWingConfigurationDialog import AirWingConfigurationDialog
from qt_ui.windows.newgame.SettingNames import RUNWAY_REPAIR, FRONTLINE, AIRCRAFT, MISSION_LENGTH, SUPER_CARRIER
from qt_ui.windows.newgame.WizardPages.QFactionSelection import FactionSelection
from qt_ui.windows.newgame.WizardPages.QGeneratorSettings import GeneratorOptions
from qt_ui.windows.newgame.WizardPages.QNewGameSettings import NewGameSettings
from qt_ui.windows.newgame.WizardPages.QTheaterConfiguration import TheaterConfiguration, TIME_PERIODS
from qt_ui.windows.newgame.WizardPages.QTheaterConfiguration import (
TheaterConfiguration,
TIME_PERIODS,
)
class NewGameWizard(QtWidgets.QWizard):
@ -33,8 +33,7 @@ class NewGameWizard(QtWidgets.QWizard):
self.addPage(self.faction_selection_page)
self.go_page = GeneratorOptions(self.campaigns[0], self)
self.addPage(self.go_page)
self.settings_page = NewGameSettings(self)
self.settings_page.set_campaign_values(self.campaigns[0])
self.settings_page = NewGameSettings(self.campaigns[0], self)
# Update difficulty page on campaign select
self.theater_page.campaign_selected.connect(lambda c: self.update_settings(c))
@ -70,21 +69,6 @@ class NewGameWizard(QtWidgets.QWizard):
start_date = self.theater_page.calendar.selectedDate().toPython()
logging.info("New campaign start date: %s", start_date.strftime("%m/%d/%Y"))
settings = Settings()
settings.__setstate__(campaign.settings)
settings.player_income_multiplier = self.field("player_income_multiplier") / 10
settings.enemy_income_multiplier = self.field("enemy_income_multiplier") / 10
settings.automate_runway_repair = self.field(RUNWAY_REPAIR)
settings.automate_front_line_reinforcements = self.field(FRONTLINE)
settings.desired_player_mission_duration = timedelta(
minutes=self.field(MISSION_LENGTH)
)
settings.enable_squadron_aircraft_limits = self.field("use_new_squadron_rules")
settings.automate_aircraft_reinforcements = self.field(AIRCRAFT)
settings.supercarrier = self.field(SUPER_CARRIER)
settings.perf_culling = (
campaign.settings.get("perf_culling_distance") is not None
)
generator_settings = GeneratorSettings(
start_date=start_date,
@ -138,6 +122,8 @@ class NewGameWizard(QtWidgets.QWizard):
logging.info("New campaign theater: %s", theater.terrain.name)
settings = self.settings_page.settings_widget.settings
generator = GameGenerator(
blue_faction,
red_faction,

View File

@ -4,7 +4,14 @@ from copy import deepcopy
from PySide2 import QtWidgets, QtGui
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QScrollArea, QWidget, QGridLayout, QCheckBox, QLabel, QTextBrowser
from PySide2.QtWidgets import (
QScrollArea,
QWidget,
QGridLayout,
QCheckBox,
QLabel,
QTextBrowser,
)
from game.campaignloader import Campaign
from game.factions import Faction, FACTIONS

View File

@ -8,8 +8,7 @@ from PySide2.QtWidgets import QLabel, QVBoxLayout
from game.campaignloader import Campaign
from game.campaignloader.campaign import DEFAULT_BUDGET
from qt_ui.widgets.spinsliders import CurrencySpinner, TimeInputs
from qt_ui.windows.newgame.SettingNames import MISSION_LENGTH, SUPER_CARRIER
from qt_ui.widgets.spinsliders import CurrencySpinner
DEFAULT_MISSION_LENGTH: timedelta = timedelta(minutes=60)
@ -51,38 +50,28 @@ class GeneratorOptions(QtWidgets.QWizardPage):
self.registerField("no_carrier", self.no_carrier)
self.no_lha = QtWidgets.QCheckBox()
self.registerField("no_lha", self.no_lha)
self.supercarrier = QtWidgets.QCheckBox()
self.registerField(SUPER_CARRIER, self.supercarrier)
self.no_player_navy = QtWidgets.QCheckBox()
self.registerField("no_player_navy", self.no_player_navy)
self.no_enemy_navy = QtWidgets.QCheckBox()
self.registerField("no_enemy_navy", self.no_enemy_navy)
self.desired_player_mission_duration = TimeInputs(
DEFAULT_MISSION_LENGTH, minimum=30, maximum=150
)
self.registerField(MISSION_LENGTH, self.desired_player_mission_duration.spinner)
generatorLayout = QtWidgets.QGridLayout()
generatorLayout.addWidget(QtWidgets.QLabel("No Aircraft Carriers"), 1, 0)
generatorLayout.addWidget(self.no_carrier, 1, 1)
generatorLayout.addWidget(QtWidgets.QLabel("No LHA"), 2, 0)
generatorLayout.addWidget(self.no_lha, 2, 1)
generatorLayout.addWidget(QtWidgets.QLabel("Use Supercarrier module"), 3, 0)
generatorLayout.addWidget(self.supercarrier, 3, 1)
generatorLayout.addWidget(QtWidgets.QLabel("No Player Navy"), 4, 0)
generatorLayout.addWidget(self.no_player_navy, 4, 1)
generatorLayout.addWidget(QtWidgets.QLabel("No Enemy Navy"), 5, 0)
generatorLayout.addWidget(self.no_enemy_navy, 5, 1)
# generatorLayout.addWidget(QtWidgets.QLabel("Desired mission duration"), 6, 0)
# generatorLayout.addLayout(self.desired_player_mission_duration, 7, 0)
generatorLayout.addWidget(QtWidgets.QLabel("No Player Navy"), 3, 0)
generatorLayout.addWidget(self.no_player_navy, 3, 1)
generatorLayout.addWidget(QtWidgets.QLabel("No Enemy Navy"), 4, 0)
generatorLayout.addWidget(self.no_enemy_navy, 4, 1)
self.player_budget = BudgetInputs("Player starting budget", DEFAULT_BUDGET)
self.registerField("starting_money", self.player_budget.starting_money)
generatorLayout.addLayout(self.player_budget, 8, 0)
generatorLayout.addLayout(self.player_budget, 5, 0)
self.enemy_budget = BudgetInputs("Enemy starting budget", DEFAULT_BUDGET)
self.registerField("enemy_starting_money", self.enemy_budget.starting_money)
generatorLayout.addLayout(self.enemy_budget, 9, 0)
generatorLayout.addLayout(self.enemy_budget, 6, 0)
generatorSettingsGroup.setLayout(generatorLayout)
@ -204,10 +193,8 @@ class GeneratorOptions(QtWidgets.QWizardPage):
self.no_carrier.setChecked(s.get("no_carrier", False))
self.no_lha.setChecked(s.get("no_lha", False))
self.supercarrier.setChecked(s.get(SUPER_CARRIER, False))
self.no_player_navy.setChecked(s.get("no_player_navy", False))
self.no_enemy_navy.setChecked(s.get("no_enemy_navy", False))
# self.desired_player_mission_duration.spinner.setValue(s.get(MISSION_LENGTH, 60))
self.a4_skyhawk.setChecked(s.get("a4_skyhawk", False))
self.a6a_intruder.setChecked(s.get("a6a_intruder", False))

View File

@ -1,84 +1,37 @@
from __future__ import unicode_literals
from PySide2 import QtWidgets, QtGui
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QLabel
from game.campaignloader import Campaign
from qt_ui.widgets.spinsliders import FloatSpinSlider
from qt_ui.windows.newgame.SettingNames import RUNWAY_REPAIR, FRONTLINE, AIRCRAFT
from game.settings import Settings
from qt_ui.windows.settings.QSettingsWindow import QSettingsWidget
class NewGameSettings(QtWidgets.QWizardPage):
def __init__(self, parent=None) -> None:
def __init__(self, campaign: Campaign, parent=None) -> None:
super().__init__(parent)
self.setTitle("Campaign options")
self.setSubTitle(
"\nAll other options unrelated to campaign generation."
)
self.setSubTitle("\nAll other options unrelated to campaign generation.")
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)
economy_layout.addWidget(QLabel("Player income multiplier"))
self.player_income = FloatSpinSlider(0, 5, 1, divisor=10)
self.registerField("player_income_multiplier", self.player_income.spinner)
economy_layout.addLayout(self.player_income)
economy_layout.addWidget(QLabel("Enemy income multiplier"))
self.enemy_income = FloatSpinSlider(0, 5, 1, divisor=10)
self.registerField("enemy_income_multiplier", self.enemy_income.spinner)
economy_layout.addLayout(self.enemy_income)
new_squadron_rules = QtWidgets.QCheckBox("Enable new squadron rules")
self.registerField("use_new_squadron_rules", new_squadron_rules)
economy_layout.addWidget(new_squadron_rules)
economy_layout.addWidget(
QLabel(
"With new squadron rules enabled, squadrons will not be able to exceed a maximum number of aircraft "
"(configurable), and the campaign will begin with all squadrons at full strength."
)
settings = Settings()
settings.__setstate__(campaign.settings)
settings.player_income_multiplier = (
campaign.recommended_player_income_multiplier
)
settings.enemy_income_multiplier = campaign.recommended_enemy_income_multiplier
settings.__dict__.update(campaign.settings)
self.settings_widget = QSettingsWidget(settings)
self.setLayout(self.settings_widget.layout)
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)
self.runway_repairs = QtWidgets.QCheckBox()
self.registerField(RUNWAY_REPAIR, self.runway_repairs)
assist_layout.addWidget(self.runway_repairs, 0, 1, Qt.AlignRight)
assist_layout.addWidget(QtWidgets.QLabel("Automate front-line purchases"), 1, 0)
self.front_line = QtWidgets.QCheckBox()
self.registerField(FRONTLINE, self.front_line)
assist_layout.addWidget(self.front_line, 1, 1, Qt.AlignRight)
assist_layout.addWidget(QtWidgets.QLabel("Automate aircraft purchases"), 2, 0)
self.aircraft = QtWidgets.QCheckBox()
self.registerField(AIRCRAFT, self.aircraft)
assist_layout.addWidget(self.aircraft, 2, 1, Qt.AlignRight)
self.setLayout(layout)
def set_campaign_values(self, campaign: Campaign) -> None:
self.player_income.spinner.setValue(
int(campaign.recommended_player_income_multiplier * 10)
)
self.enemy_income.spinner.setValue(
int(campaign.recommended_enemy_income_multiplier * 10)
)
s = campaign.settings
self.runway_repairs.setChecked(s.get(RUNWAY_REPAIR, False))
self.front_line.setChecked(s.get(FRONTLINE, False))
self.aircraft.setChecked(s.get(AIRCRAFT, False))
def set_campaign_values(self, c: Campaign):
sw = self.settings_widget
sw.settings.player_income_multiplier = c.recommended_player_income_multiplier
sw.settings.enemy_income_multiplier = c.recommended_enemy_income_multiplier
sw.settings.__dict__.update(c.settings)
print(sw.settings.__dict__)
sw.update_from_settings()

View File

@ -6,7 +6,14 @@ from typing import List, Optional
from PySide2 import QtWidgets, QtGui
from PySide2.QtCore import Signal, QDate, QPoint, QItemSelectionModel, Qt, QModelIndex
from PySide2.QtGui import QStandardItem, QPixmap, QStandardItemModel
from PySide2.QtWidgets import QCheckBox, QTextBrowser, QTextEdit, QLabel, QListView, QAbstractItemView
from PySide2.QtWidgets import (
QCheckBox,
QTextBrowser,
QTextEdit,
QLabel,
QListView,
QAbstractItemView,
)
from game.campaignloader import Campaign
from qt_ui.liberation_install import get_dcs_install_directory

View File

@ -1,9 +1,10 @@
import json
import logging
import textwrap
from typing import Callable
import zipfile
from typing import Callable, Optional, Dict
from PySide2 import QtWidgets
from PySide2.QtCore import QItemSelectionModel, QPoint, QSize, Qt
from PySide2.QtGui import QStandardItem, QStandardItemModel
from PySide2.QtWidgets import (
@ -37,6 +38,7 @@ from game.settings import (
OptionDescription,
Settings,
)
from game.settings.ISettingsContainer import SettingsContainer
from game.sim import GameUpdateEvents
from qt_ui.widgets.QLabeledWidget import QLabeledWidget
from qt_ui.widgets.spinsliders import FloatSpinSlider, TimeInputs
@ -45,27 +47,29 @@ from qt_ui.windows.settings.plugins import PluginOptionsPage, PluginsPage
class CheatSettingsBox(QGroupBox):
def __init__(self, game: Game, apply_settings: Callable[[], None]) -> None:
def __init__(
self, sc: SettingsContainer, apply_settings: Callable[[], None]
) -> None:
super().__init__("Cheat Settings")
self.main_layout = QVBoxLayout()
self.setLayout(self.main_layout)
self.red_ato_checkbox = QCheckBox()
self.red_ato_checkbox.setChecked(game.settings.show_red_ato)
self.red_ato_checkbox.setChecked(sc.settings.show_red_ato)
self.red_ato_checkbox.toggled.connect(apply_settings)
self.frontline_cheat_checkbox = QCheckBox()
self.frontline_cheat_checkbox.setChecked(game.settings.enable_frontline_cheats)
self.frontline_cheat_checkbox.setChecked(sc.settings.enable_frontline_cheats)
self.frontline_cheat_checkbox.toggled.connect(apply_settings)
self.base_capture_cheat_checkbox = QCheckBox()
self.base_capture_cheat_checkbox.setChecked(
game.settings.enable_base_capture_cheat
sc.settings.enable_base_capture_cheat
)
self.base_capture_cheat_checkbox.toggled.connect(apply_settings)
self.transfer_cheat_checkbox = QCheckBox()
self.transfer_cheat_checkbox.setChecked(game.settings.enable_transfer_cheat)
self.transfer_cheat_checkbox.setChecked(sc.settings.enable_transfer_cheat)
self.transfer_cheat_checkbox.toggled.connect(apply_settings)
self.red_ato = QLabeledWidget("Show Red ATO:", self.red_ato_checkbox)
@ -105,14 +109,22 @@ class AutoSettingsLayout(QGridLayout):
self,
page: str,
section: str,
settings: Settings,
sc: SettingsContainer,
write_full_settings: Callable[[], None],
) -> None:
super().__init__()
self.settings = settings
self.page = page
self.section = section
self.sc = sc
self.write_full_settings = write_full_settings
self.settings_map: Dict[str, QWidget] = {}
for row, (name, description) in enumerate(Settings.fields(page, section)):
self.init_ui()
def init_ui(self):
for row, (name, description) in enumerate(
Settings.fields(self.page, self.section)
):
self.add_label(row, description)
if isinstance(description, BooleanOption):
self.add_checkbox_for(row, name, description)
@ -142,31 +154,33 @@ class AutoSettingsLayout(QGridLayout):
def on_toggle(value: bool) -> None:
if description.invert:
value = not value
self.settings.__dict__[name] = value
self.sc.settings.__dict__[name] = value
if description.causes_expensive_game_update:
self.write_full_settings()
checkbox = QCheckBox()
value = self.settings.__dict__[name]
value = self.sc.settings.__dict__[name]
if description.invert:
value = not value
checkbox.setChecked(value)
checkbox.toggled.connect(on_toggle)
self.addWidget(checkbox, row, 1, Qt.AlignRight)
self.settings_map[name] = checkbox
def add_combobox_for(self, row: int, name: str, description: ChoicesOption) -> None:
combobox = QComboBox()
def on_changed(index: int) -> None:
self.settings.__dict__[name] = combobox.itemData(index)
self.sc.settings.__dict__[name] = combobox.itemData(index)
for text, value in description.choices.items():
combobox.addItem(text, value)
combobox.setCurrentText(
description.text_for_value(self.settings.__dict__[name])
description.text_for_value(self.sc.settings.__dict__[name])
)
combobox.currentIndexChanged.connect(on_changed)
self.addWidget(combobox, row, 1, Qt.AlignRight)
self.settings_map[name] = combobox
def add_float_spin_slider_for(
self, row: int, name: str, description: BoundedFloatOption
@ -174,44 +188,62 @@ class AutoSettingsLayout(QGridLayout):
spinner = FloatSpinSlider(
description.min,
description.max,
self.settings.__dict__[name],
self.sc.settings.__dict__[name],
divisor=description.divisor,
)
def on_changed() -> None:
self.settings.__dict__[name] = spinner.value
self.sc.settings.__dict__[name] = spinner.value
spinner.spinner.valueChanged.connect(on_changed)
self.addLayout(spinner, row, 1, Qt.AlignRight)
self.settings_map[name] = spinner
def add_spinner_for(
self, row: int, name: str, description: BoundedIntOption
) -> None:
def on_changed(value: int) -> None:
self.settings.__dict__[name] = value
self.sc.settings.__dict__[name] = value
if description.causes_expensive_game_update:
self.write_full_settings()
spinner = QSpinBox()
spinner.setMinimum(description.min)
spinner.setMaximum(description.max)
spinner.setValue(self.settings.__dict__[name])
spinner.setValue(self.sc.settings.__dict__[name])
spinner.valueChanged.connect(on_changed)
self.addWidget(spinner, row, 1, Qt.AlignRight)
self.settings_map[name] = spinner
def add_duration_controls_for(
self, row: int, name: str, description: MinutesOption
) -> None:
inputs = TimeInputs(
self.settings.__dict__[name], description.min, description.max
self.sc.settings.__dict__[name], description.min, description.max
)
def on_changed() -> None:
self.settings.__dict__[name] = inputs.value
self.sc.settings.__dict__[name] = inputs.value
inputs.spinner.valueChanged.connect(on_changed)
self.addLayout(inputs, row, 1, Qt.AlignRight)
self.settings_map[name] = inputs
def update_from_settings(self) -> None:
for name, description in Settings.fields(self.page, self.section):
widget = self.settings_map[name]
value = self.sc.settings.__dict__[name]
if isinstance(widget, QCheckBox):
widget.setChecked(value)
elif isinstance(widget, QComboBox):
widget.setCurrentText(description.text_for_value(value))
elif isinstance(widget, FloatSpinSlider):
widget.spinner.setValue(int(value * widget.spinner.divisor))
elif isinstance(widget, QSpinBox):
widget.setValue(value)
elif isinstance(widget, TimeInputs):
widget.spinner.setValue(value.seconds // 60)
class AutoSettingsGroup(QGroupBox):
@ -219,57 +251,80 @@ class AutoSettingsGroup(QGroupBox):
self,
page: str,
section: str,
settings: Settings,
sc: SettingsContainer,
write_full_settings: Callable[[], None],
) -> None:
super().__init__(section)
self.setLayout(AutoSettingsLayout(page, section, settings, write_full_settings))
self.layout = AutoSettingsLayout(page, section, sc, write_full_settings)
self.setLayout(self.layout)
def update_from_settings(self) -> None:
self.layout.update_from_settings()
class AutoSettingsPageLayout(QVBoxLayout):
def __init__(
self,
page: str,
settings: Settings,
sc: SettingsContainer,
write_full_settings: Callable[[], None],
) -> None:
super().__init__()
self.setAlignment(Qt.AlignTop)
self.widgets = []
for section in Settings.sections(page):
self.addWidget(
AutoSettingsGroup(page, section, settings, write_full_settings)
self.widgets.append(
AutoSettingsGroup(page, section, sc, write_full_settings)
)
self.addWidget(self.widgets[-1])
def update_from_settings(self) -> None:
for w in self.widgets:
w.update_from_settings()
class AutoSettingsPage(QWidget):
def __init__(
self,
page: str,
settings: Settings,
sc: SettingsContainer,
write_full_settings: Callable[[], None],
) -> None:
super().__init__()
self.setLayout(AutoSettingsPageLayout(page, settings, write_full_settings))
self.layout = AutoSettingsPageLayout(page, sc, write_full_settings)
self.setLayout(self.layout)
def update_from_settings(self) -> None:
self.layout.update_from_settings()
class QSettingsWindow(QDialog):
def __init__(self, game: Game):
super().__init__()
self.game = game
self.pluginsPage = None
self.pluginsOptionsPage = None
self.pages: dict[str, AutoSettingsPage] = {}
for page in Settings.pages():
self.pages[page] = AutoSettingsPage(page, game.settings, self.applySettings)
self.setLayout(QSettingsWidget(game.settings, game).layout)
self.setModal(True)
self.setWindowTitle("Settings")
self.setWindowIcon(CONST.ICONS["Settings"])
self.setMinimumSize(840, 480)
class QSettingsWidget(QtWidgets.QWizardPage, SettingsContainer):
def __init__(self, settings: Settings, game: Optional[Game] = None):
super().__init__()
self.settings = game.settings if game else settings
self.game = game
self.pages: dict[str, AutoSettingsPage] = {}
for page in Settings.pages():
self.pages[page] = AutoSettingsPage(page, self, self.applySettings)
self.pluginsPage = PluginsPage(self)
self.pluginsOptionsPage = PluginOptionsPage(self)
self.initUi()
def initUi(self):
@ -306,7 +361,6 @@ class QSettingsWindow(QDialog):
self.categoryModel.appendRow(cheat)
self.right_layout.addWidget(self.cheatPage)
self.pluginsPage = PluginsPage()
plugins = QStandardItem("LUA Plugins")
plugins.setIcon(CONST.ICONS["Plugins"])
plugins.setEditable(False)
@ -314,7 +368,6 @@ class QSettingsWindow(QDialog):
self.categoryModel.appendRow(plugins)
self.right_layout.addWidget(self.pluginsPage)
self.pluginsOptionsPage = PluginOptionsPage()
pluginsOptions = QStandardItem("LUA Plugins Options")
pluginsOptions.setIcon(CONST.ICONS["PluginsOptions"])
pluginsOptions.setEditable(False)
@ -351,10 +404,11 @@ class QSettingsWindow(QDialog):
self.cheatLayout = QVBoxLayout()
self.cheatPage.setLayout(self.cheatLayout)
self.cheat_options = CheatSettingsBox(self.game, self.applySettings)
self.cheat_options = CheatSettingsBox(self, self.applySettings)
self.cheatLayout.addWidget(self.cheat_options)
self.moneyCheatBox = QGroupBox("Money Cheat")
self.moneyCheatBox.setDisabled(self.game is None)
self.moneyCheatBox.setAlignment(Qt.AlignTop)
self.moneyCheatBoxLayout = QGridLayout()
self.moneyCheatBox.setLayout(self.moneyCheatBoxLayout)
@ -380,26 +434,41 @@ class QSettingsWindow(QDialog):
GameUpdateSignal.get_instance().updateGame(self.game)
def applySettings(self):
self.game.settings.show_red_ato = self.cheat_options.show_red_ato
self.game.settings.enable_frontline_cheats = (
self.cheat_options.show_frontline_cheat
)
self.game.settings.enable_base_capture_cheat = (
self.settings.show_red_ato = self.cheat_options.show_red_ato
self.settings.enable_frontline_cheats = self.cheat_options.show_frontline_cheat
self.settings.enable_base_capture_cheat = (
self.cheat_options.show_base_capture_cheat
)
self.game.settings.enable_transfer_cheat = (
self.cheat_options.show_transfer_cheat
)
self.settings.enable_transfer_cheat = self.cheat_options.show_transfer_cheat
if self.game:
events = GameUpdateEvents()
self.game.compute_unculled_zones(events)
EventStream.put_nowait(events)
GameUpdateSignal.get_instance().updateGame(self.game)
def onSelectionChanged(self):
def onSelectionChanged(self) -> None:
index = self.categoryList.selectionModel().currentIndex().row()
self.right_layout.setCurrentIndex(index)
def update_from_settings(self) -> None:
for p in self.pages.values():
p.update_from_settings()
self.cheat_options.red_ato_checkbox.setChecked(self.settings.show_red_ato)
self.cheat_options.base_capture_cheat_checkbox.setChecked(
self.settings.enable_base_capture_cheat
)
self.cheat_options.frontline_cheat_checkbox.setChecked(
self.settings.enable_frontline_cheats
)
self.cheat_options.transfer_cheat_checkbox.setChecked(
self.settings.enable_transfer_cheat
)
self.pluginsPage.update_from_settings()
self.pluginsOptionsPage.update_from_settings()
def load_settings(self):
sd = settings_dir()
if not sd.exists():
@ -411,12 +480,10 @@ class QSettingsWindow(QDialog):
filename = zipfilename.split("/")[-1].replace(".zip", ".json")
settings = json.loads(
zf.read(filename).decode("utf-8"),
object_hook=self.game.settings.obj_hook,
object_hook=self.settings.obj_hook,
)
self.game.settings.__setstate__(settings)
self.close()
new = QSettingsWindow(self.game)
new.exec_()
self.settings.__setstate__(settings)
self.update_from_settings()
def save_settings(self):
sd = settings_dir()
@ -431,9 +498,9 @@ class QSettingsWindow(QDialog):
zf.writestr(
filename,
json.dumps(
self.game.settings.__dict__,
self.settings.__dict__,
indent=2,
default=self.game.settings.default_json,
default=self.settings.default_json,
),
zipfile.ZIP_DEFLATED,
)

View File

@ -1,3 +1,5 @@
from typing import Dict, List
from PySide2.QtCore import Qt, QLocale
from PySide2.QtWidgets import (
QCheckBox,
@ -11,6 +13,8 @@ from PySide2.QtWidgets import (
)
from game.plugins import LuaPlugin, LuaPluginManager
from game.settings import Settings
from game.settings.ISettingsContainer import SettingsContainer
class PluginsBox(QGroupBox):
@ -21,6 +25,8 @@ class PluginsBox(QGroupBox):
layout.setAlignment(Qt.AlignTop)
self.setLayout(layout)
self.plugin_map: Dict[str, QCheckBox] = {}
for row, plugin in enumerate(LuaPluginManager.plugins()):
if not plugin.show_in_ui:
continue
@ -31,17 +37,29 @@ class PluginsBox(QGroupBox):
checkbox.setChecked(plugin.get_value)
checkbox.toggled.connect(plugin.set_value)
layout.addWidget(checkbox, row, 1)
self.plugin_map[plugin.identifier] = checkbox
def update_from_settings(self, settings: Settings):
for identifier, enabled in settings.plugins.items():
if identifier in self.plugin_map:
self.plugin_map[identifier].setChecked(enabled)
class PluginsPage(QWidget):
def __init__(self) -> None:
def __init__(self, sc: SettingsContainer) -> None:
super().__init__()
self.sc = sc
layout = QVBoxLayout()
layout.setAlignment(Qt.AlignTop)
self.setLayout(layout)
layout.addWidget(PluginsBox())
self.plugins_box = PluginsBox()
layout.addWidget(self.plugins_box)
def update_from_settings(self):
self.plugins_box.update_from_settings(self.sc.settings)
class PluginOptionsBox(QGroupBox):
@ -52,6 +70,8 @@ class PluginOptionsBox(QGroupBox):
layout.setAlignment(Qt.AlignTop)
self.setLayout(layout)
self.widgets: Dict[str, QWidget] = {}
for row, option in enumerate(plugin.options):
layout.addWidget(QLabel(option.name), row, 0)
@ -61,6 +81,7 @@ class PluginOptionsBox(QGroupBox):
checkbox.setChecked(val)
checkbox.toggled.connect(option.set_value)
layout.addWidget(checkbox, row, 1)
self.widgets[option.identifier] = checkbox
elif type(val) == float or type(val) == int:
if type(val) == float:
spinbox = QDoubleSpinBox()
@ -73,16 +94,36 @@ class PluginOptionsBox(QGroupBox):
spinbox.setValue(val)
spinbox.valueChanged.connect(option.set_value)
layout.addWidget(spinbox, row, 1)
self.widgets[option.identifier] = spinbox
def update_from_settings(self, settings: Settings) -> None:
for identifier in self.widgets:
value = settings.plugin_option(identifier)
w = self.widgets[identifier]
if isinstance(w, QCheckBox):
w.setChecked(value)
elif isinstance(w, QDoubleSpinBox) or isinstance(w, QSpinBox):
w.setValue(value)
class PluginOptionsPage(QWidget):
def __init__(self) -> None:
def __init__(self, sc: SettingsContainer) -> None:
super().__init__()
self.sc = sc
layout = QVBoxLayout()
layout.setAlignment(Qt.AlignTop)
self.setLayout(layout)
self.pobs: List[PluginOptionsBox] = []
for plugin in LuaPluginManager.plugins():
if plugin.options:
layout.addWidget(PluginOptionsBox(plugin))
pob = PluginOptionsBox(plugin)
layout.addWidget(pob)
self.pobs.append(pob)
def update_from_settings(self):
for pob in self.pobs:
pob.update_from_settings(self.sc.settings)

View File

@ -17,6 +17,7 @@ recommended_enemy_income_multiplier: 1.0
advanced_iads: false
settings:
max_frontline_length: 30
player_income_multiplier: 1.5
squadrons:
CVN-74 John Stennis:
- primary: BARCAP