diff --git a/game/game.py b/game/game.py index a4087ec1..f5040dd0 100644 --- a/game/game.py +++ b/game/game.py @@ -150,17 +150,13 @@ class Game: front_line.control_point_b) @property - def budget_reward_amount(self): - reward = 0 - if len(self.theater.player_points()) > 0: - reward = PLAYER_BUDGET_BASE * len(self.theater.player_points()) - for cp in self.theater.player_points(): - for g in cp.ground_objects: - if g.category in REWARDS.keys() and not g.is_dead: - reward = reward + REWARDS[g.category] - return reward - else: - return reward + def budget_reward_amount(self) -> int: + reward = PLAYER_BUDGET_BASE * len(self.theater.player_points()) + for cp in self.theater.player_points(): + for g in cp.ground_objects: + if g.category in REWARDS.keys() and not g.is_dead: + reward += REWARDS[g.category] + return int(reward * self.settings.player_income_multiplier) def _budget_player(self): self.budget += self.budget_reward_amount @@ -182,7 +178,8 @@ class Game: def finish_event(self, event: Event, debriefing: Debriefing): logging.info("Finishing event {}".format(event)) event.commit(debriefing) - self.budget += event.bonus() + self.budget += int(event.bonus() * + self.settings.player_income_multiplier) if event in self.events: self.events.remove(event) @@ -272,8 +269,7 @@ class Game: if g.category in REWARDS.keys() and not g.is_dead: production = production + REWARDS[g.category] - # TODO: Why doesn't the enemy get the full budget? - budget = production * 0.75 + budget = production * self.settings.enemy_income_multiplier for control_point in self.theater.enemy_points(): if budget < db.RUNWAY_REPAIR_COST: diff --git a/game/settings.py b/game/settings.py index c85f5c28..8dae3061 100644 --- a/game/settings.py +++ b/game/settings.py @@ -22,6 +22,8 @@ class Settings: manpads: bool = True cold_start: bool = False # Legacy parameter do not use version: Optional[str] = None + player_income_multiplier: float = 1.0 + enemy_income_multiplier: float = 1.0 # Performance oriented perf_red_alert_state: bool = True diff --git a/qt_ui/widgets/floatspinners.py b/qt_ui/widgets/floatspinners.py new file mode 100644 index 00000000..058b3516 --- /dev/null +++ b/qt_ui/widgets/floatspinners.py @@ -0,0 +1,20 @@ +from typing import Optional + +from PySide2.QtWidgets import QSpinBox + + +class TenthsSpinner(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"X {val / 10:.1f}" diff --git a/qt_ui/widgets/spinsliders.py b/qt_ui/widgets/spinsliders.py new file mode 100644 index 00000000..1b63862b --- /dev/null +++ b/qt_ui/widgets/spinsliders.py @@ -0,0 +1,26 @@ +from PySide2.QtCore import Qt +from PySide2.QtWidgets import QGridLayout, QLabel, QSlider + +from qt_ui.widgets.floatspinners import TenthsSpinner + + +class TenthsSpinSlider(QGridLayout): + def __init__(self, label: str, minimum: int, maximum: int, + initial: int) -> None: + super().__init__() + self.addWidget(QLabel(label), 0, 0) + + slider = QSlider(Qt.Horizontal) + slider.setMinimum(minimum) + slider.setMaximum(maximum) + slider.setValue(initial) + self.spinner = TenthsSpinner(minimum, maximum, initial) + slider.valueChanged.connect(lambda x: self.spinner.setValue(x)) + self.spinner.valueChanged.connect(lambda x: slider.setValue(x)) + + self.addWidget(slider, 1, 0) + self.addWidget(self.spinner, 1, 1) + + @property + def value(self) -> float: + return self.spinner.value() / 10 diff --git a/qt_ui/windows/finances/QFinancesMenu.py b/qt_ui/windows/finances/QFinancesMenu.py index 362f642c..67cd27c9 100644 --- a/qt_ui/windows/finances/QFinancesMenu.py +++ b/qt_ui/windows/finances/QFinancesMenu.py @@ -64,7 +64,11 @@ class QFinancesMenu(QDialog): self.setLayout(layout) - layout.addWidget(QHorizontalSeparationLine(), i+1, 0, 1, 3) - - layout.addWidget(QLabel("" + str(self.game.budget_reward_amount) + "M "), i+2, 2) - + layout.addWidget(QHorizontalSeparationLine(), i + 1, 0, 1, 3) + layout.addWidget(QLabel( + f"Income multiplier: {game.settings.player_income_multiplier:.1f}"), + i + 2, 1 + ) + layout.addWidget( + QLabel("" + str(self.game.budget_reward_amount) + "M "), + i + 2, 2) diff --git a/qt_ui/windows/newgame/QNewGameWizard.py b/qt_ui/windows/newgame/QNewGameWizard.py index 65b7becc..704f9a9c 100644 --- a/qt_ui/windows/newgame/QNewGameWizard.py +++ b/qt_ui/windows/newgame/QNewGameWizard.py @@ -10,6 +10,7 @@ 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, @@ -56,7 +57,10 @@ class NewGameWizard(QtWidgets.QWizard): campaign = self.campaigns[0] settings = Settings( - supercarrier=self.field("supercarrier"), + player_income_multiplier=self.field( + "player_income_multiplier") / 10, + enemy_income_multiplier=self.field("enemy_income_multiplier") / 10, + supercarrier=self.field("supercarrier") ) generator_settings = GeneratorSettings( start_date=db.TIME_PERIODS[ @@ -321,44 +325,6 @@ class BudgetInputs(QtWidgets.QGridLayout): self.addWidget(self.starting_money, 1, 1) -class ForceMultiplierSpinner(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"X {val / 10:.1f}" - - -class ForceMultiplierInputs(QtWidgets.QGridLayout): - def __init__(self) -> None: - super().__init__() - self.addWidget(QtWidgets.QLabel("Enemy forces multiplier"), 0, 0) - - minimum = 1 - maximum = 50 - initial = 10 - - slider = QtWidgets.QSlider(Qt.Horizontal) - slider.setMinimum(minimum) - slider.setMaximum(maximum) - slider.setValue(initial) - self.multiplier = ForceMultiplierSpinner(minimum, maximum, initial) - slider.valueChanged.connect(lambda x: self.multiplier.setValue(x)) - self.multiplier.valueChanged.connect(lambda x: slider.setValue(x)) - - self.addWidget(slider, 1, 0) - self.addWidget(self.multiplier, 1, 1) - - class MiscOptions(QtWidgets.QWizardPage): def __init__(self, parent=None): super(MiscOptions, self).__init__(parent) @@ -369,9 +335,14 @@ class MiscOptions(QtWidgets.QWizardPage): QtGui.QPixmap('./resources/ui/wizard/logo1.png')) midGame = QtWidgets.QCheckBox() - multiplier_inputs = ForceMultiplierInputs() - self.registerField('multiplier', multiplier_inputs.multiplier) + multiplier = TenthsSpinSlider("Enemy forces multiplier", 1, 50, 10) + self.registerField('multiplier', multiplier.spinner) + player_income = TenthsSpinSlider("Player income multiplier", 1, 50, 10) + self.registerField("player_income_multiplier", player_income.spinner) + + enemy_income = TenthsSpinSlider("Enemy income multiplier", 1, 50, 10) + self.registerField("enemy_income_multiplier", enemy_income.spinner) miscSettingsGroup = QtWidgets.QGroupBox("Misc Settings") self.registerField('midGame', midGame) @@ -392,7 +363,9 @@ class MiscOptions(QtWidgets.QWizardPage): layout = QtWidgets.QGridLayout() layout.addWidget(QtWidgets.QLabel("Start at mid game"), 1, 0) layout.addWidget(midGame, 1, 1) - layout.addLayout(multiplier_inputs, 2, 0) + layout.addLayout(multiplier, 2, 0) + layout.addLayout(player_income, 3, 0) + layout.addLayout(enemy_income, 4, 0) miscSettingsGroup.setLayout(layout) generatorLayout = QtWidgets.QGridLayout() diff --git a/qt_ui/windows/settings/QSettingsWindow.py b/qt_ui/windows/settings/QSettingsWindow.py index 0bf0de82..fae49153 100644 --- a/qt_ui/windows/settings/QSettingsWindow.py +++ b/qt_ui/windows/settings/QSettingsWindow.py @@ -24,6 +24,7 @@ import qt_ui.uiconstants as CONST from game.game import Game from game.infos.information import Information from qt_ui.widgets.QLabeledWidget import QLabeledWidget +from qt_ui.widgets.spinsliders import TenthsSpinSlider from qt_ui.windows.GameUpdateSignal import GameUpdateSignal from qt_ui.windows.finances.QFinancesMenu import QHorizontalSeparationLine from qt_ui.windows.settings.plugins import PluginOptionsPage, PluginsPage @@ -150,6 +151,15 @@ class QSettingsWindow(QDialog): self.enemyCoalitionSkill.setCurrentIndex(CONST.SKILL_OPTIONS.index(self.game.settings.enemy_skill)) self.enemyAASkill.setCurrentIndex(CONST.SKILL_OPTIONS.index(self.game.settings.enemy_vehicle_skill)) + self.player_income = TenthsSpinSlider( + "Player income multiplier", 1, 50, + int(self.game.settings.player_income_multiplier * 10)) + self.player_income.spinner.valueChanged.connect(self.applySettings) + self.enemy_income = TenthsSpinSlider( + "Enemy income multiplier", 1, 50, + int(self.game.settings.enemy_income_multiplier * 10)) + self.enemy_income.spinner.valueChanged.connect(self.applySettings) + self.playerCoalitionSkill.currentIndexChanged.connect(self.applySettings) self.enemyCoalitionSkill.currentIndexChanged.connect(self.applySettings) self.enemyAASkill.currentIndexChanged.connect(self.applySettings) @@ -203,6 +213,8 @@ class QSettingsWindow(QDialog): self.aiDifficultyLayout.addWidget(self.enemyCoalitionSkill, 1, 1, Qt.AlignRight) self.aiDifficultyLayout.addWidget(QLabel("Enemy AA and vehicles skill"), 2, 0) self.aiDifficultyLayout.addWidget(self.enemyAASkill, 2, 1, Qt.AlignRight) + self.aiDifficultyLayout.addLayout(self.player_income, 3, 0) + self.aiDifficultyLayout.addLayout(self.enemy_income, 4, 0) self.aiDifficultySettings.setLayout(self.aiDifficultyLayout) self.difficultyLayout.addWidget(self.aiDifficultySettings) @@ -377,6 +389,8 @@ class QSettingsWindow(QDialog): self.game.settings.player_skill = CONST.SKILL_OPTIONS[self.playerCoalitionSkill.currentIndex()] self.game.settings.enemy_skill = CONST.SKILL_OPTIONS[self.enemyCoalitionSkill.currentIndex()] self.game.settings.enemy_vehicle_skill = CONST.SKILL_OPTIONS[self.enemyAASkill.currentIndex()] + self.game.settings.player_income_multiplier = self.player_income.value + self.game.settings.enemy_income_multiplier = self.enemy_income.value self.game.settings.manpads = self.manpads.isChecked() self.game.settings.labels = CONST.LABELS_OPTIONS[self.difficultyLabel.currentIndex()] self.game.settings.night_disabled = self.noNightMission.isChecked()