diff --git a/game/settings.py b/game/settings.py
index 4602bd55..0e6f968a 100644
--- a/game/settings.py
+++ b/game/settings.py
@@ -31,6 +31,7 @@ class Settings:
automate_aircraft_reinforcements: bool = False
restrict_weapons_by_date: bool = False
disable_legacy_aewc: bool = False
+ generate_dark_kneeboard: bool = False
# Performance oriented
perf_red_alert_state: bool = True
diff --git a/gen/kneeboard.py b/gen/kneeboard.py
index b87f91cb..a99eb9a5 100644
--- a/gen/kneeboard.py
+++ b/gen/kneeboard.py
@@ -49,8 +49,16 @@ if TYPE_CHECKING:
class KneeboardPageWriter:
"""Creates kneeboard images."""
- def __init__(self, page_margin: int = 24, line_spacing: int = 12) -> None:
- self.image = Image.new("RGB", (768, 1024), (0xFF, 0xFF, 0xFF))
+ def __init__(
+ self, page_margin: int = 24, line_spacing: int = 12, dark_theme: bool = False
+ ) -> None:
+ if dark_theme:
+ self.foreground_fill = (215, 200, 200)
+ self.background_fill = (10, 5, 5)
+ else:
+ self.foreground_fill = (15, 15, 15)
+ self.background_fill = (255, 252, 252)
+ self.image = Image.new("RGB", (768, 1024), self.background_fill)
# These font sizes create a relatively full page for current sorties. If
# we start generating more complicated flight plans, or start including
# more information in the comm ladder (the latter of which we should
@@ -80,10 +88,10 @@ class KneeboardPageWriter:
self.y += height + self.line_spacing
def title(self, title: str) -> None:
- self.text(title, font=self.title_font)
+ self.text(title, font=self.title_font, fill=self.foreground_fill)
def heading(self, text: str) -> None:
- self.text(text, font=self.heading_font)
+ self.text(text, font=self.heading_font, fill=self.foreground_fill)
def table(
self, cells: List[List[str]], headers: Optional[List[str]] = None
@@ -91,7 +99,7 @@ class KneeboardPageWriter:
if headers is None:
headers = []
table = tabulate(cells, headers=headers, numalign="right")
- self.text(table, font=self.table_font)
+ self.text(table, font=self.table_font, fill=self.foreground_fill)
def write(self, path: Path) -> None:
self.image.save(path)
@@ -238,6 +246,7 @@ class BriefingPage(KneeboardPage):
tankers: List[TankerInfo],
jtacs: List[JtacInfo],
start_time: datetime.datetime,
+ dark_kneeboard: bool,
) -> None:
self.flight = flight
self.comms = list(comms)
@@ -245,10 +254,11 @@ class BriefingPage(KneeboardPage):
self.tankers = tankers
self.jtacs = jtacs
self.start_time = start_time
+ self.dark_kneeboard = dark_kneeboard
self.comms.append(CommInfo("Flight", self.flight.intra_flight_channel))
def write(self, path: Path) -> None:
- writer = KneeboardPageWriter()
+ writer = KneeboardPageWriter(dark_theme=self.dark_kneeboard)
if self.flight.custom_name is not None:
custom_name_title = ' ("{}")'.format(self.flight.custom_name)
else:
@@ -402,6 +412,9 @@ class KneeboardGenerator(MissionInfoGenerator):
def __init__(self, mission: Mission, game: "Game") -> None:
super().__init__(mission, game)
+ self.dark_kneeboard = self.game.settings.generate_dark_kneeboard and (
+ self.mission.start_time.hour > 19 or self.mission.start_time.hour < 7
+ )
def generate(self) -> None:
"""Generates a kneeboard per client flight."""
@@ -445,5 +458,6 @@ class KneeboardGenerator(MissionInfoGenerator):
self.tankers,
self.jtacs,
self.mission.start_time,
+ self.dark_kneeboard,
),
]
diff --git a/qt_ui/windows/settings/QSettingsWindow.py b/qt_ui/windows/settings/QSettingsWindow.py
index b0c85152..ceba6e1b 100644
--- a/qt_ui/windows/settings/QSettingsWindow.py
+++ b/qt_ui/windows/settings/QSettingsWindow.py
@@ -422,6 +422,12 @@ class QSettingsWindow(QDialog):
self.generate_marks.setChecked(self.game.settings.generate_marks)
self.generate_marks.toggled.connect(self.applySettings)
+ self.generate_dark_kneeboard = QCheckBox()
+ self.generate_dark_kneeboard.setChecked(
+ self.game.settings.generate_dark_kneeboard
+ )
+ self.generate_dark_kneeboard.toggled.connect(self.applySettings)
+
self.never_delay_players = QCheckBox()
self.never_delay_players.setChecked(
self.game.settings.never_delay_player_flights
@@ -437,6 +443,14 @@ class QSettingsWindow(QDialog):
self.gameplayLayout.addWidget(QLabel("Put Objective Markers on Map"), 1, 0)
self.gameplayLayout.addWidget(self.generate_marks, 1, 1, Qt.AlignRight)
+ dark_kneeboard_label = QLabel(
+ "Generate Dark Kneeboard
"
+ "Dark kneeboard for night missions.
"
+ "This will likely make the kneeboard on the pilot leg unreadable."
+ )
+ self.gameplayLayout.addWidget(dark_kneeboard_label, 2, 0)
+ self.gameplayLayout.addWidget(self.generate_dark_kneeboard, 2, 1, Qt.AlignRight)
+
spawn_players_immediately_tooltip = (
"Always spawns player aircraft immediately, even if their start time is "
"more than 10 minutes after the start of the mission. This does "
@@ -449,8 +463,8 @@ class QSettingsWindow(QDialog):
"Should not be used if players have runway or in-air starts."
)
spawn_immediately_label.setToolTip(spawn_players_immediately_tooltip)
- self.gameplayLayout.addWidget(spawn_immediately_label, 2, 0)
- self.gameplayLayout.addWidget(self.never_delay_players, 2, 1, Qt.AlignRight)
+ self.gameplayLayout.addWidget(spawn_immediately_label, 3, 0)
+ self.gameplayLayout.addWidget(self.never_delay_players, 3, 1, Qt.AlignRight)
start_type_label = QLabel(
"Default start type for AI aircraft
Warning: "
@@ -460,8 +474,8 @@ class QSettingsWindow(QDialog):
start_type = StartTypeComboBox(self.game.settings)
start_type.setCurrentText(self.game.settings.default_start_type)
- self.gameplayLayout.addWidget(start_type_label, 3, 0)
- self.gameplayLayout.addWidget(start_type, 3, 1)
+ self.gameplayLayout.addWidget(start_type_label, 4, 0)
+ self.gameplayLayout.addWidget(start_type, 4, 1)
self.performance = QGroupBox("Performance")
self.performanceLayout = QGridLayout()
@@ -629,6 +643,10 @@ class QSettingsWindow(QDialog):
self.game.settings.supercarrier = self.supercarrier.isChecked()
+ self.game.settings.generate_dark_kneeboard = (
+ self.generate_dark_kneeboard.isChecked()
+ )
+
self.game.settings.perf_red_alert_state = self.red_alert.isChecked()
self.game.settings.perf_smoke_gen = self.smoke.isChecked()
self.game.settings.perf_artillery = self.arti.isChecked()