diff --git a/changelog.md b/changelog.md
index c5016a58..69a72793 100644
--- a/changelog.md
+++ b/changelog.md
@@ -2,9 +2,12 @@
## Features/Improvements :
* **[Other]** Added an installer option (thanks to contributor parithon)
+* **[Cheat Menu]** Added possibility to replace destroyed SAM and base defenses units for the player (Click on a SAM site to fix it)
+* **[Cheat Menu]** Added recon images for buildings on strike targets, click on a Strike target to get detailled informations
* **[Units/Factions]** Added F-16C to USA 1990
* **[Units/Factions]** Added MQ-9 Reaper as CAS unit for USA 2005
* **[Units/Factions]** Added Mig-21, Mig-23, SA-342L to Syria 2011
+* **[Cheat Menu]** Added buttons to remove money
## Fixed issues :
* **[UI/UX]** Spelling issues (Thanks to Github contributor steveveepee)
diff --git a/game/data/building_data.py b/game/data/building_data.py
index 6236a9e1..f88415ce 100644
--- a/game/data/building_data.py
+++ b/game/data/building_data.py
@@ -6,7 +6,7 @@ DEFAULT_AVAILABLE_BUILDINGS = ['fuel', 'ammo', 'comms', 'oil', 'ware', 'farp', '
WW2_GERMANY_BUILDINGS = ['fuel', 'factory', 'ww2bunker', 'ww2bunker', 'ww2bunker', 'allycamp', 'allycamp', 'aa']
WW2_ALLIES_BUILDINGS = ['fuel', 'factory', 'allycamp', 'allycamp', 'allycamp', 'allycamp', 'allycamp', 'aa']
-FORTIFICATION_BUILDINGS = ['Siegfried Line', 'Concertina Wire', 'Czech hedgehogs 1', 'Czech hedgehogs 2',
+FORTIFICATION_BUILDINGS = ['Siegfried Line', 'Concertina wire', 'Concertina Wire', 'Czech hedgehogs 1', 'Czech hedgehogs 2',
'Dragonteeth 1', 'Dragonteeth 2', 'Dragonteeth 3', 'Dragonteeth 4', 'Dragonteeth 5',
'Haystack 1', 'Haystack 2', 'Haystack 3', 'Haystack 4', 'Hemmkurvenvenhindernis',
'Log posts 1', 'Log posts 2', 'Log posts 3', 'Log ramps 1', 'Log ramps 2', 'Log ramps 3',
diff --git a/qt_ui/widgets/map/QLiberationMap.py b/qt_ui/widgets/map/QLiberationMap.py
index 5311fac4..41194ca0 100644
--- a/qt_ui/widgets/map/QLiberationMap.py
+++ b/qt_ui/widgets/map/QLiberationMap.py
@@ -143,7 +143,7 @@ class QLiberationMap(QGraphicsView):
go_pos = self._transform_point(ground_object.position)
if not ground_object.airbase_group:
buildings = self.game.theater.find_ground_objects_by_obj_name(ground_object.obj_name)
- scene.addItem(QMapGroundObject(self, go_pos[0], go_pos[1], 12, 12, cp, ground_object, self.game, buildings))
+ scene.addItem(QMapGroundObject(self, go_pos[0], go_pos[1], 14, 12, cp, ground_object, self.game, buildings))
if ground_object.category == "aa" and self.get_display_rule("sam"):
max_range = 0
diff --git a/qt_ui/widgets/map/QMapGroundObject.py b/qt_ui/widgets/map/QMapGroundObject.py
index d2950f3a..a79ce1ab 100644
--- a/qt_ui/widgets/map/QMapGroundObject.py
+++ b/qt_ui/widgets/map/QMapGroundObject.py
@@ -1,9 +1,10 @@
from PySide2.QtCore import QPoint, QRect, QPointF, Qt
-from PySide2.QtGui import QPainter
+from PySide2.QtGui import QPainter, QBrush
from PySide2.QtWidgets import QGraphicsRectItem, QGraphicsItem, QGraphicsSceneHoverEvent, QGraphicsSceneMouseEvent
import qt_ui.uiconstants as CONST
from game import db, Game
+from game.data.building_data import FORTIFICATION_BUILDINGS
from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
from theater import TheaterGroundObject, ControlPoint
@@ -57,14 +58,49 @@ class QMapGroundObject(QGraphicsRectItem):
if cat == "aa" and self.model.sea_object:
cat = "ship"
- if not self.model.is_dead and not self.cp.captured:
- painter.drawPixmap(option.rect, CONST.ICONS[cat + enemyIcons])
- elif not self.model.is_dead:
- painter.drawPixmap(option.rect, CONST.ICONS[cat + playerIcons])
+ rect = QRect(option.rect.x()+2,option.rect.y(),option.rect.width()-2,option.rect.height())
+
+ is_dead = self.model.is_dead
+ for building in self.buildings:
+ if not building.is_dead:
+ is_dead = False
+ break
+
+ if not is_dead and not self.cp.captured:
+ painter.drawPixmap(rect, CONST.ICONS[cat + enemyIcons])
+ elif not is_dead:
+ painter.drawPixmap(rect, CONST.ICONS[cat + playerIcons])
else:
- painter.drawPixmap(option.rect, CONST.ICONS["destroyed"])
+ painter.drawPixmap(rect, CONST.ICONS["destroyed"])
+
+ self.drawHealthGauge(painter, option)
painter.restore()
+ def drawHealthGauge(self, painter, option):
+ units_alive = 0
+ units_dead = 0
+
+ if len(self.model.groups) == 0:
+ for building in self.buildings:
+ if building.dcs_identifier in FORTIFICATION_BUILDINGS:
+ continue
+ if building.is_dead:
+ units_dead += 1
+ else:
+ units_alive += 1
+
+ for g in self.model.groups:
+ units_alive += len(g.units)
+ if hasattr(g, "units_losts"):
+ units_dead += len(g.units_losts)
+
+ if units_dead + units_alive > 0:
+ ratio = float(units_alive)/(float(units_dead) + float(units_alive))
+ bar_height = ratio * option.rect.height()
+ painter.fillRect(option.rect.x(), option.rect.y(), 2, option.rect.height(), QBrush(CONST.COLORS["dark_red"]))
+ painter.fillRect(option.rect.x(), option.rect.y(), 2, bar_height, QBrush(CONST.COLORS["green"]))
+
+
def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent):
self.update()
self.setCursor(Qt.PointingHandCursor)
@@ -77,6 +113,6 @@ class QMapGroundObject(QGraphicsRectItem):
self.update()
def openEditionMenu(self):
- self.editionMenu = QGroundObjectMenu(self.window(), self.model, self.cp, self.game)
+ self.editionMenu = QGroundObjectMenu(self.window(), self.model, self.buildings, self.cp, self.game)
self.editionMenu.show()
diff --git a/qt_ui/windows/basemenu/base_defenses/QBaseDefenseGroupInfo.py b/qt_ui/windows/basemenu/base_defenses/QBaseDefenseGroupInfo.py
index c3f3d454..2b2abb67 100644
--- a/qt_ui/windows/basemenu/base_defenses/QBaseDefenseGroupInfo.py
+++ b/qt_ui/windows/basemenu/base_defenses/QBaseDefenseGroupInfo.py
@@ -1,16 +1,22 @@
-from PySide2.QtWidgets import QGridLayout, QLabel, QGroupBox
+from PySide2.QtWidgets import QGridLayout, QLabel, QGroupBox, QPushButton
from qt_ui.uiconstants import VEHICLES_ICONS
+from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
from theater import ControlPoint, TheaterGroundObject
class QBaseDefenseGroupInfo(QGroupBox):
- def __init__(self, cp:ControlPoint, ground_object: TheaterGroundObject):
+ def __init__(self, cp:ControlPoint, ground_object: TheaterGroundObject, game):
super(QBaseDefenseGroupInfo, self).__init__("Group : " + ground_object.obj_name)
self.ground_object = ground_object
+ self.cp = cp
+ self.game = game
+ self.buildings = game.theater.find_ground_objects_by_obj_name(self.ground_object.obj_name)
self.init_ui()
+
+
def init_ui(self):
unit_dict = {}
layout = QGridLayout()
@@ -29,8 +35,18 @@ class QBaseDefenseGroupInfo(QGroupBox):
# icon.setText("" + k[:6] + "")
#icon.setProperty("style", "icon-plane")
#layout.addWidget(icon, i, 0)
- layout.addWidget(QLabel(str(v) + " x " + "" + k + ""), i, 1)
+ layout.addWidget(QLabel(str(v) + " x " + "" + k + ""), i, 0)
i = i + 1
+
+ manage_button = QPushButton("Manage")
+ manage_button.setProperty("style", "btn-success")
+ manage_button.setMaximumWidth(180)
+ manage_button.clicked.connect(self.onManage)
+ layout.addWidget(manage_button, i+1, 0)
self.setLayout(layout)
+ def onManage(self):
+ self.editionMenu = QGroundObjectMenu(self.window(), self.ground_object, self.buildings, self.cp, self.game)
+ self.editionMenu.show()
+
diff --git a/qt_ui/windows/basemenu/base_defenses/QBaseDefensesHQ.py b/qt_ui/windows/basemenu/base_defenses/QBaseDefensesHQ.py
index 77c53939..5ad1f6c9 100644
--- a/qt_ui/windows/basemenu/base_defenses/QBaseDefensesHQ.py
+++ b/qt_ui/windows/basemenu/base_defenses/QBaseDefensesHQ.py
@@ -15,6 +15,6 @@ class QBaseDefensesHQ(QFrame):
def init_ui(self):
airport = self.game.theater.terrain.airport_by_id(self.cp.id)
layout = QGridLayout()
- layout.addWidget(QBaseInformation(self.cp, airport))
+ layout.addWidget(QBaseInformation(self.cp, airport, self.game))
self.setLayout(layout)
diff --git a/qt_ui/windows/basemenu/base_defenses/QBaseInformation.py b/qt_ui/windows/basemenu/base_defenses/QBaseInformation.py
index 7ae07483..c98113b6 100644
--- a/qt_ui/windows/basemenu/base_defenses/QBaseInformation.py
+++ b/qt_ui/windows/basemenu/base_defenses/QBaseInformation.py
@@ -1,4 +1,5 @@
-from PySide2.QtWidgets import QGridLayout, QLabel, QGroupBox, QVBoxLayout, QFrame
+from PySide2.QtGui import Qt
+from PySide2.QtWidgets import QGridLayout, QLabel, QGroupBox, QVBoxLayout, QFrame, QWidget, QScrollArea
from game import db
from qt_ui.uiconstants import AIRCRAFT_ICONS, VEHICLES_ICONS
@@ -8,17 +9,34 @@ from theater import ControlPoint, Airport
class QBaseInformation(QFrame):
- def __init__(self, cp:ControlPoint, airport:Airport):
+ def __init__(self, cp:ControlPoint, airport:Airport, game):
super(QBaseInformation, self).__init__()
self.cp = cp
self.airport = airport
+ self.game = game
self.setMinimumWidth(500)
self.init_ui()
def init_ui(self):
- self.layout = QVBoxLayout()
+ self.mainLayout = QVBoxLayout()
+
+ scroll_content = QWidget()
+ task_box_layout = QGridLayout()
+ scroll_content.setLayout(task_box_layout)
+ row = 0
+
for g in self.cp.ground_objects:
if g.airbase_group:
- group_info = QBaseDefenseGroupInfo(self.cp, g)
- self.layout.addWidget(group_info)
- self.setLayout(self.layout)
+ group_info = QBaseDefenseGroupInfo(self.cp, g, self.game)
+ task_box_layout.addWidget(group_info)
+
+ scroll_content.setLayout(task_box_layout)
+ scroll = QScrollArea()
+ scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+ scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
+ scroll.setWidgetResizable(True)
+ scroll.setWidget(scroll_content)
+
+ self.mainLayout.addWidget(scroll)
+
+ self.setLayout(self.mainLayout)
\ No newline at end of file
diff --git a/qt_ui/windows/groundobject/QBuildingInfo.py b/qt_ui/windows/groundobject/QBuildingInfo.py
new file mode 100644
index 00000000..e474a59f
--- /dev/null
+++ b/qt_ui/windows/groundobject/QBuildingInfo.py
@@ -0,0 +1,33 @@
+import os
+
+from PySide2.QtGui import QPixmap
+from PySide2.QtWidgets import QGroupBox, QHBoxLayout, QVBoxLayout, QLabel
+
+
+class QBuildingInfo(QGroupBox):
+
+ def __init__(self, building, ground_object):
+ super(QBuildingInfo, self).__init__()
+ self.building = building
+ self.ground_object = ground_object
+ self.init_ui()
+
+ def init_ui(self):
+ self.header = QLabel()
+ path = os.path.join("./resources/ui/units/buildings/" + self.building.dcs_identifier + ".png")
+ if self.building.is_dead:
+ pixmap = QPixmap("./resources/ui/units/buildings/dead.png")
+ elif os.path.isfile(path):
+ pixmap = QPixmap(path)
+ else:
+ pixmap = QPixmap("./resources/ui/units/buildings/missing.png")
+ self.header.setPixmap(pixmap)
+ name = "{} {}".format(self.building.dcs_identifier[0:18], "[DEAD]" if self.building.is_dead else "")
+ self.name = QLabel(name)
+ self.name.setProperty("style", "small")
+ layout = QVBoxLayout()
+ layout.addWidget(self.header)
+ layout.addWidget(self.name)
+ footer = QHBoxLayout()
+ self.setLayout(layout)
+
diff --git a/qt_ui/windows/groundobject/QGroundObjectMenu.py b/qt_ui/windows/groundobject/QGroundObjectMenu.py
index ad8d0ff7..b6c90027 100644
--- a/qt_ui/windows/groundobject/QGroundObjectMenu.py
+++ b/qt_ui/windows/groundobject/QGroundObjectMenu.py
@@ -5,23 +5,30 @@ from PySide2.QtWidgets import QHBoxLayout, QWidget, QDialog, QGridLayout, QLabel
from dcs import Point
from game import Game
+from game.data.building_data import FORTIFICATION_BUILDINGS
from game.db import PRICES, unit_type_of
+from qt_ui.uiconstants import EVENT_ICONS
from qt_ui.widgets.QBudgetBox import QBudgetBox
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
+from qt_ui.windows.groundobject.QBuildingInfo import QBuildingInfo
from theater import ControlPoint, TheaterGroundObject
class QGroundObjectMenu(QDialog):
- def __init__(self, parent, ground_object: TheaterGroundObject, cp: ControlPoint, game: Game):
+ def __init__(self, parent, ground_object: TheaterGroundObject, buildings:[], cp: ControlPoint, game: Game):
super(QGroundObjectMenu, self).__init__(parent)
self.setMinimumWidth(350)
self.ground_object = ground_object
+ self.buildings = buildings
self.cp = cp
self.game = game
self.setWindowTitle("Location " + self.ground_object.obj_name)
+ self.setWindowIcon(EVENT_ICONS["capture"])
self.intelBox = QGroupBox("Units :")
+ self.buildingBox = QGroupBox("Buildings :")
self.intelLayout = QGridLayout()
+ self.buildingsLayout = QGridLayout()
self.init_ui()
def init_ui(self):
@@ -32,7 +39,10 @@ class QGroundObjectMenu(QDialog):
self.doLayout()
- self.mainLayout.addWidget(self.intelBox)
+ if len(self.ground_object.groups) > 0:
+ self.mainLayout.addWidget(self.intelBox)
+ else:
+ self.mainLayout.addWidget(self.buildingBox)
self.setLayout(self.mainLayout)
def doLayout(self):
@@ -55,28 +65,37 @@ class QGroundObjectMenu(QDialog):
price = 6
self.intelLayout.addWidget(QLabel("Unit #" + str(u.id) + " - " + str(u.type) + " [DEAD]"), i, 0)
- repair = QPushButton("Repair [" + str(price) + "M]")
- repair.setProperty("style", "btn-primary")
- repair.clicked.connect(lambda u=u, g=g, p=price: self.repair_unit(g, u, p))
- self.intelLayout.addWidget(repair, i, 1)
+ if self.cp.captured:
+ repair = QPushButton("Repair [" + str(price) + "M]")
+ repair.setProperty("style", "btn-success")
+ repair.clicked.connect(lambda u=u, g=g, p=price: self.repair_unit(g, u, p))
+ self.intelLayout.addWidget(repair, i, 1)
i = i + 1
+
+ self.buildingBox = QGroupBox("Buildings :")
+ self.buildingsLayout = QGridLayout()
+ j = 0
+ for i, building in enumerate(self.buildings):
+ if building.dcs_identifier not in FORTIFICATION_BUILDINGS:
+ self.buildingsLayout.addWidget(QBuildingInfo(building, self.ground_object), j/3, j%3)
+ j = j + 1
+
+ self.buildingBox.setLayout(self.buildingsLayout)
self.intelBox.setLayout(self.intelLayout)
def do_refresh_layout(self):
try:
for i in range(self.mainLayout.count()):
- self.mainLayout.removeItem(self.mainLayout.itemAt(i));
+ self.mainLayout.removeItem(self.mainLayout.itemAt(i))
self.doLayout()
- self.mainLayout.addWidget(self.intelBox)
+ if len(self.ground_object.groups) > 0:
+ self.mainLayout.addWidget(self.intelBox)
+ else:
+ self.mainLayout.addWidget(self.buildingBox)
except Exception as e:
print(e)
def repair_unit(self, group, unit, price):
-
- print(group)
- print(unit.type)
- [print(u.id) for u in group.units]
-
if self.game.budget > price:
self.game.budget -= price
group.units_losts = [u for u in group.units_losts if u.id != unit.id]
diff --git a/resources/stylesheets/style-dcs.css b/resources/stylesheets/style-dcs.css
index c01f398c..57b2478b 100644
--- a/resources/stylesheets/style-dcs.css
+++ b/resources/stylesheets/style-dcs.css
@@ -486,3 +486,7 @@ QWidget[style="baseMenuHeader"]{
font-weight: bold;
color:white;
}*/
+
+QLabel[style="small"]{
+ font-size: 8px;
+}
\ No newline at end of file
diff --git a/resources/stylesheets/style.css b/resources/stylesheets/style.css
index a8b65845..b382f642 100644
--- a/resources/stylesheets/style.css
+++ b/resources/stylesheets/style.css
@@ -178,4 +178,8 @@ QLabel[style="SEAD"]{
QWidget[style="baseMenuHeader"]{
font-size: 24px;
font-weight: bold;
-}*/
\ No newline at end of file
+}*/
+
+QLabel[style="small"]{
+ font-size: 8px;
+}
\ No newline at end of file