mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Flesh out intel displays.
* Add enemy air and ground unit reports. * Changes the summary to be a comparison of relative strengths rather than raw enemy numbers. Fixes https://github.com/Khopa/dcs_liberation/issues/658
This commit is contained in:
parent
1f4516b954
commit
3bdf1377c0
@ -19,6 +19,7 @@ Saves from 2.3 are not compatible with 2.4.
|
||||
* **[Factions]** Updated Nato Desert Storm to include F-14A
|
||||
* **[Factions]** Updated Iraq 1991 factions to include Zsu-57 and Mig-29A
|
||||
* **[Plugins]** [The EWRS plugin](https://github.com/Bob7heBuilder/EWRS) is now included.
|
||||
* **[UI]** Added enemy intelligence summary and details window.
|
||||
|
||||
## Fixes:
|
||||
* **[Factions]** AI would never buy artillery units for the frontline - fixed
|
||||
|
||||
@ -1,32 +1,42 @@
|
||||
from typing import Optional
|
||||
|
||||
from PySide2.QtWidgets import (
|
||||
QGridLayout,
|
||||
QGroupBox,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
from game import Game
|
||||
from game.income import Income
|
||||
from qt_ui.windows.intel import IntelWindow
|
||||
|
||||
|
||||
class QIntelBox(QGroupBox):
|
||||
def __init__(self, game: Game) -> None:
|
||||
super().__init__("Intel")
|
||||
self.setProperty("style", "IntelSummary")
|
||||
|
||||
self.game = game
|
||||
|
||||
columns = QHBoxLayout()
|
||||
self.setLayout(columns)
|
||||
|
||||
summary = QVBoxLayout()
|
||||
summary = QGridLayout()
|
||||
columns.addLayout(summary)
|
||||
|
||||
self.total_aircraft = QLabel()
|
||||
summary.addWidget(self.total_aircraft)
|
||||
self.total_ground_forces = QLabel()
|
||||
summary.addWidget(self.total_ground_forces)
|
||||
summary.addWidget(QLabel("Air superiority:"), 0, 0)
|
||||
self.air_strength = QLabel()
|
||||
summary.addWidget(self.air_strength, 0, 1)
|
||||
|
||||
summary.addWidget(QLabel("Front line:"), 1, 0)
|
||||
self.ground_strength = QLabel()
|
||||
summary.addWidget(self.ground_strength, 1, 1)
|
||||
|
||||
summary.addWidget(QLabel("Economic strength:"), 2, 0)
|
||||
self.economic_strength = QLabel()
|
||||
summary.addWidget(self.economic_strength, 2, 1)
|
||||
|
||||
details = QPushButton("Details")
|
||||
columns.addWidget(details)
|
||||
@ -40,17 +50,57 @@ class QIntelBox(QGroupBox):
|
||||
self.game = game
|
||||
self.update_summary()
|
||||
|
||||
@staticmethod
|
||||
def forces_strength_text(own: int, enemy: int) -> str:
|
||||
if not enemy:
|
||||
return "enemy eliminated"
|
||||
|
||||
ratio = own / enemy
|
||||
if ratio < 0.6:
|
||||
return "outnumbered"
|
||||
if ratio < 0.8:
|
||||
return "slightly outnumbered"
|
||||
if ratio < 1.2:
|
||||
return "evenly matched"
|
||||
if ratio < 1.4:
|
||||
return "slight advantage"
|
||||
return "strong advantage"
|
||||
|
||||
def economic_strength_text(self) -> str:
|
||||
assert self.game is not None
|
||||
own = Income(self.game, player=True).total
|
||||
enemy = Income(self.game, player=False).total
|
||||
|
||||
if not enemy:
|
||||
return "enemy economy ruined"
|
||||
|
||||
ratio = own / enemy
|
||||
if ratio < 0.6:
|
||||
return "strong disadvantage"
|
||||
if ratio < 0.8:
|
||||
return "slight disadvantage"
|
||||
if ratio < 1.2:
|
||||
return "evenly matched"
|
||||
if ratio < 1.4:
|
||||
return "slight advantage"
|
||||
return "strong advantage"
|
||||
|
||||
def update_summary(self) -> None:
|
||||
if self.game is None:
|
||||
aircraft = 0
|
||||
ground_units = 0
|
||||
else:
|
||||
data = self.game.game_stats.data_per_turn[-1]
|
||||
aircraft = data.enemy_units.aircraft_count
|
||||
ground_units = data.enemy_units.vehicles_count
|
||||
self.total_aircraft.setText(f"Total enemy aircraft: {aircraft}")
|
||||
self.total_ground_forces.setText(
|
||||
f"Total enemy ground units: {ground_units}")
|
||||
self.air_strength.setText("no data")
|
||||
self.ground_strength.setText("no data")
|
||||
self.economic_strength.setText("no data")
|
||||
return
|
||||
|
||||
data = self.game.game_stats.data_per_turn[-1]
|
||||
|
||||
self.air_strength.setText(self.forces_strength_text(
|
||||
data.allied_units.aircraft_count,
|
||||
data.enemy_units.aircraft_count))
|
||||
self.ground_strength.setText(self.forces_strength_text(
|
||||
data.allied_units.vehicles_count,
|
||||
data.enemy_units.vehicles_count))
|
||||
self.economic_strength.setText(self.economic_strength_text())
|
||||
|
||||
def open_details_window(self) -> None:
|
||||
self.details_window = IntelWindow(self.game)
|
||||
|
||||
@ -1,7 +1,15 @@
|
||||
import itertools
|
||||
|
||||
from PySide2.QtWidgets import (
|
||||
QDialog,
|
||||
QGroupBox,
|
||||
QFrame,
|
||||
QGridLayout,
|
||||
QLabel,
|
||||
QLayout,
|
||||
QScrollArea,
|
||||
QSizePolicy,
|
||||
QSpacerItem,
|
||||
QTabWidget,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
@ -11,22 +19,115 @@ from qt_ui.uiconstants import ICONS
|
||||
from qt_ui.windows.finances.QFinancesMenu import FinancesLayout
|
||||
|
||||
|
||||
class EconomyIntelBox(QGroupBox):
|
||||
def __init__(self, game: Game) -> None:
|
||||
super().__init__("Economy")
|
||||
class ScrollingFrame(QFrame):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
widget = QWidget()
|
||||
scroll_area = QScrollArea()
|
||||
scroll_area.setWidgetResizable(True)
|
||||
scroll_area.setWidget(widget)
|
||||
|
||||
scrolling_layout = QVBoxLayout()
|
||||
widget.setLayout(scrolling_layout)
|
||||
self.scrolling_layout = QVBoxLayout()
|
||||
widget.setLayout(self.scrolling_layout)
|
||||
|
||||
self.setLayout(QVBoxLayout())
|
||||
self.layout().addWidget(scroll_area)
|
||||
|
||||
scrolling_layout.addLayout(FinancesLayout(game, player=False))
|
||||
def addWidget(self, widget: QWidget, *args, **kwargs) -> None:
|
||||
self.scrolling_layout.addWidget(widget, *args, **kwargs)
|
||||
|
||||
def addLayout(self, layout: QLayout, *args, **kwargs) -> None:
|
||||
self.scrolling_layout.addLayout(layout, *args, **kwargs)
|
||||
|
||||
|
||||
class EconomyIntelTab(ScrollingFrame):
|
||||
def __init__(self, game: Game) -> None:
|
||||
super().__init__()
|
||||
self.addLayout(FinancesLayout(game, player=False))
|
||||
|
||||
|
||||
class IntelTableLayout(QGridLayout):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.row = itertools.count(0)
|
||||
|
||||
def add_header(self, text: str) -> None:
|
||||
self.addWidget(QLabel(f"<b>{text}</b>"), next(self.row), 0)
|
||||
|
||||
def add_spacer(self) -> None:
|
||||
self.addItem(
|
||||
QSpacerItem(0, 0, QSizePolicy.Preferred, QSizePolicy.Expanding),
|
||||
next(self.row), 0)
|
||||
|
||||
def add_row(self, text: str, count: int) -> None:
|
||||
row = next(self.row)
|
||||
self.addWidget(QLabel(text), row, 0)
|
||||
self.addWidget(QLabel(str(count)), row, 1)
|
||||
|
||||
|
||||
class AircraftIntelLayout(IntelTableLayout):
|
||||
def __init__(self, game: Game, player: bool) -> None:
|
||||
super().__init__()
|
||||
|
||||
total = 0
|
||||
for control_point in game.theater.control_points_for(player):
|
||||
base = control_point.base
|
||||
total += base.total_aircraft
|
||||
if not base.total_aircraft:
|
||||
continue
|
||||
|
||||
self.add_header(control_point.name)
|
||||
for airframe, count in base.aircraft.items():
|
||||
if not count:
|
||||
continue
|
||||
self.add_row(airframe.id, count)
|
||||
|
||||
self.add_spacer()
|
||||
self.add_row("<b>Total</b>", total)
|
||||
|
||||
|
||||
class AircraftIntelTab(ScrollingFrame):
|
||||
def __init__(self, game: Game) -> None:
|
||||
super().__init__()
|
||||
self.addLayout(AircraftIntelLayout(game, player=False))
|
||||
|
||||
|
||||
class ArmyIntelLayout(IntelTableLayout):
|
||||
def __init__(self, game: Game, player: bool) -> None:
|
||||
super().__init__()
|
||||
|
||||
total = 0
|
||||
for control_point in game.theater.control_points_for(player):
|
||||
base = control_point.base
|
||||
total += base.total_armor
|
||||
if not base.total_armor:
|
||||
continue
|
||||
|
||||
self.add_header(control_point.name)
|
||||
for vehicle, count in base.armor.items():
|
||||
if not count:
|
||||
continue
|
||||
self.add_row(vehicle.id, count)
|
||||
|
||||
self.add_spacer()
|
||||
self.add_row("<b>Total</b>", total)
|
||||
|
||||
|
||||
class ArmyIntelTab(ScrollingFrame):
|
||||
def __init__(self, game: Game) -> None:
|
||||
super().__init__()
|
||||
self.addLayout(ArmyIntelLayout(game, player=False))
|
||||
|
||||
|
||||
class IntelTabs(QTabWidget):
|
||||
|
||||
def __init__(self, game: Game):
|
||||
super().__init__()
|
||||
|
||||
self.addTab(EconomyIntelTab(game), "Economy")
|
||||
self.addTab(AircraftIntelTab(game), "Air forces")
|
||||
self.addTab(ArmyIntelTab(game), "Ground forces")
|
||||
|
||||
|
||||
class IntelWindow(QDialog):
|
||||
@ -38,9 +139,9 @@ class IntelWindow(QDialog):
|
||||
self.setModal(True)
|
||||
self.setWindowTitle("Intelligence")
|
||||
self.setWindowIcon(ICONS["Statistics"])
|
||||
self.setMinimumSize(800, 600)
|
||||
self.setMinimumSize(600, 500)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
self.setLayout(layout)
|
||||
|
||||
layout.addWidget(EconomyIntelBox(game), stretch=1)
|
||||
layout.addWidget(IntelTabs(game), stretch=1)
|
||||
|
||||
@ -546,7 +546,7 @@ QGroupBox[style="QWeatherWidget"] {
|
||||
padding: 0px;
|
||||
margin-left: 0px;
|
||||
margin-right: 5px;
|
||||
margin-top: 1ex;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
@ -555,4 +555,22 @@ QGroupBox[style="QWeatherWidget"] QLabel[style="text-sm"] {
|
||||
margin: 0px;
|
||||
font-size: 9px;
|
||||
line-height: 9px;
|
||||
}
|
||||
|
||||
QGroupBox[style="IntelSummary"] {
|
||||
padding-left: 40px;
|
||||
padding-right: 0px;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
margin-left: 0px;
|
||||
margin-right: 5px;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
QGroupBox[style="IntelSummary"] QLabel {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
font-size: 9px;
|
||||
line-height: 9px;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user