mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Compare commits
5 Commits
4.1.1
...
develop-4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40b147148b | ||
|
|
2f56bae3e5 | ||
|
|
6febf546a8 | ||
|
|
7754e5fd4d | ||
|
|
81058d9e25 |
14
changelog.md
14
changelog.md
@@ -1,3 +1,17 @@
|
||||
# 4.1.2
|
||||
|
||||
Saves from 4.1.1 are compatible with 4.1.2.
|
||||
|
||||
## Features/Improvements
|
||||
|
||||
* **[Mission Generation]** EWRs are now also headed towards the center of the conflict
|
||||
* **[UI]** Sell Button for aircraft will be disabled if there are no units available to be sold or all are already assigned to a mission
|
||||
|
||||
## Fixes
|
||||
|
||||
* **[UI]** Selling of Units is now visible again in the UI dialog and shows the correct amount of sold units
|
||||
* **[Mission Generation]** Mission results and other files will now be opened with enforced utf-8 encoding to prevent an issue where destroyed ground units were untracked because of special characters in their names.
|
||||
|
||||
# 4.1.1
|
||||
|
||||
Saves from 4.1.0 are compatible with 4.1.1.
|
||||
|
||||
@@ -288,7 +288,7 @@ class AircraftType(UnitType[Type[FlyingType]]):
|
||||
logging.warning(f"No data for {aircraft.id}; it will not be available")
|
||||
return
|
||||
|
||||
with data_path.open() as data_file:
|
||||
with data_path.open(encoding="utf-8") as data_file:
|
||||
data = yaml.safe_load(data_file)
|
||||
|
||||
try:
|
||||
|
||||
@@ -67,7 +67,7 @@ class GroundUnitType(UnitType[Type[VehicleType]]):
|
||||
logging.warning(f"No data for {vehicle.id}; it will not be available")
|
||||
return
|
||||
|
||||
with data_path.open() as data_file:
|
||||
with data_path.open(encoding="utf-8") as data_file:
|
||||
data = yaml.safe_load(data_file)
|
||||
|
||||
try:
|
||||
|
||||
@@ -389,7 +389,7 @@ class PollDebriefingFileThread(threading.Thread):
|
||||
os.path.isfile("state.json")
|
||||
and os.path.getmtime("state.json") > last_modified
|
||||
):
|
||||
with open("state.json", "r") as json_file:
|
||||
with open("state.json", "r", encoding="utf-8") as json_file:
|
||||
json_data = json.load(json_file)
|
||||
debriefing = Debriefing(json_data, self.game, self.unit_map)
|
||||
self.callback(debriefing)
|
||||
|
||||
@@ -63,7 +63,7 @@ class Operation:
|
||||
|
||||
@classmethod
|
||||
def prepare(cls, game: Game) -> None:
|
||||
with open("resources/default_options.lua", "r") as f:
|
||||
with open("resources/default_options.lua", "r", encoding="utf-8") as f:
|
||||
options_dict = loads(f.read())["options"]
|
||||
cls._set_mission(Mission(game.theater.terrain))
|
||||
cls.game = game
|
||||
|
||||
@@ -39,9 +39,8 @@ class PendingUnitDeliveries:
|
||||
|
||||
def sell(self, units: dict[UnitType[Any], int]) -> None:
|
||||
for k, v in units.items():
|
||||
if self.units[k] > v:
|
||||
self.units[k] -= v
|
||||
else:
|
||||
self.units[k] -= v
|
||||
if self.units[k] == 0:
|
||||
del self.units[k]
|
||||
|
||||
def refund_all(self, game: Game) -> None:
|
||||
|
||||
@@ -3,7 +3,7 @@ from pathlib import Path
|
||||
|
||||
MAJOR_VERSION = 4
|
||||
MINOR_VERSION = 1
|
||||
MICRO_VERSION = 1
|
||||
MICRO_VERSION = 2
|
||||
|
||||
|
||||
def _build_version_string() -> str:
|
||||
@@ -12,7 +12,7 @@ def _build_version_string() -> str:
|
||||
]
|
||||
build_number_path = Path("resources/buildnumber")
|
||||
if build_number_path.exists():
|
||||
with build_number_path.open("r") as build_number_file:
|
||||
with build_number_path.open("r", encoding="utf-8") as build_number_file:
|
||||
components.append(build_number_file.readline())
|
||||
|
||||
if not Path("resources/final").exists():
|
||||
|
||||
@@ -16,7 +16,11 @@ class EwrGenerator(VehicleGroupGenerator[EwrGroundObject]):
|
||||
|
||||
def generate(self) -> None:
|
||||
self.add_unit(
|
||||
self.unit_type, "EWR", self.position.x, self.position.y, self.heading
|
||||
self.unit_type,
|
||||
"EWR",
|
||||
self.position.x,
|
||||
self.position.y,
|
||||
self.heading_to_conflict(),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -68,7 +68,8 @@ def run_ui(game: Optional[Game]) -> None:
|
||||
# init the theme and load the stylesheet based on the theme index
|
||||
liberation_theme.init()
|
||||
with open(
|
||||
"./resources/stylesheets/" + liberation_theme.get_theme_css_file()
|
||||
"./resources/stylesheets/" + liberation_theme.get_theme_css_file(),
|
||||
encoding="utf-8",
|
||||
) as stylesheet:
|
||||
logging.info("Loading stylesheet: %s", liberation_theme.get_theme_css_file())
|
||||
app.setStyleSheet(stylesheet.read())
|
||||
|
||||
@@ -228,7 +228,7 @@ class QWaitingForMissionResultWindow(QDialog):
|
||||
)
|
||||
print(file)
|
||||
try:
|
||||
with open(file[0], "r") as json_file:
|
||||
with open(file[0], "r", encoding="utf-8") as json_file:
|
||||
json_data = json.load(json_file)
|
||||
json_data["mission_ended"] = True
|
||||
debriefing = Debriefing(json_data, self.game, self.unit_map)
|
||||
|
||||
@@ -80,7 +80,13 @@ class PurchaseGroup(QGroupBox):
|
||||
|
||||
def update_state(self) -> None:
|
||||
self.buy_button.setEnabled(self.recruiter.enable_purchase(self.unit_type))
|
||||
self.buy_button.setToolTip(
|
||||
self.recruiter.purchase_tooltip(self.buy_button.isEnabled())
|
||||
)
|
||||
self.sell_button.setEnabled(self.recruiter.enable_sale(self.unit_type))
|
||||
self.sell_button.setToolTip(
|
||||
self.recruiter.sell_tooltip(self.sell_button.isEnabled())
|
||||
)
|
||||
self.amount_bought.setText(f"<b>{self.pending_units}</b>")
|
||||
|
||||
|
||||
@@ -223,6 +229,18 @@ class QRecruitBehaviour:
|
||||
def enable_sale(self, unit_type: UnitType) -> bool:
|
||||
return True
|
||||
|
||||
def purchase_tooltip(self, is_enabled: bool) -> str:
|
||||
if is_enabled:
|
||||
return "Buy unit. Use Shift or Ctrl key to buy multiple units at once."
|
||||
else:
|
||||
return "Unit can not be bought."
|
||||
|
||||
def sell_tooltip(self, is_enabled: bool) -> str:
|
||||
if is_enabled:
|
||||
return "Sell unit. Use Shift or Ctrl key to buy multiple units at once."
|
||||
else:
|
||||
return "Unit can not be sold."
|
||||
|
||||
def info(self, unit_type: UnitType) -> None:
|
||||
self.info_window = QUnitInfoWindow(self.game_model.game, unit_type)
|
||||
self.info_window.show()
|
||||
|
||||
@@ -85,9 +85,13 @@ class QAircraftRecruitmentMenu(QFrame, QRecruitBehaviour):
|
||||
return True
|
||||
|
||||
def enable_sale(self, unit_type: AircraftType) -> bool:
|
||||
if not self.cp.can_operate(unit_type):
|
||||
return False
|
||||
return True
|
||||
return self.can_be_sold(unit_type)
|
||||
|
||||
def sell_tooltip(self, is_enabled: bool) -> str:
|
||||
if is_enabled:
|
||||
return "Sell unit. Use Shift or Ctrl key to sell multiple units at once."
|
||||
else:
|
||||
return "Can not be sold because either no aircraft are available or are already assigned to a mission."
|
||||
|
||||
def buy(self, unit_type: AircraftType) -> bool:
|
||||
if self.maximum_units > 0:
|
||||
@@ -112,24 +116,32 @@ class QAircraftRecruitmentMenu(QFrame, QRecruitBehaviour):
|
||||
self.hangar_status.update_label()
|
||||
return True
|
||||
|
||||
def can_be_sold(self, unit_type: AircraftType) -> bool:
|
||||
inventory = self.game_model.game.aircraft_inventory.for_control_point(self.cp)
|
||||
pending_deliveries = self.pending_deliveries.units.get(unit_type, 0)
|
||||
return self.cp.can_operate(unit_type) and (
|
||||
pending_deliveries > 0 or inventory.available(unit_type) > 0
|
||||
)
|
||||
|
||||
def sell(self, unit_type: AircraftType) -> bool:
|
||||
# Don't need to remove aircraft from the inventory if we're canceling
|
||||
# orders.
|
||||
if self.pending_deliveries.units.get(unit_type, 0) <= 0:
|
||||
global_inventory = self.game_model.game.aircraft_inventory
|
||||
inventory = global_inventory.for_control_point(self.cp)
|
||||
try:
|
||||
inventory.remove_aircraft(unit_type, 1)
|
||||
except ValueError:
|
||||
QMessageBox.critical(
|
||||
self,
|
||||
"Could not sell aircraft",
|
||||
f"Attempted to sell one {unit_type} at {self.cp.name} "
|
||||
"but none are available. Are all aircraft currently "
|
||||
"assigned to a mission?",
|
||||
QMessageBox.Ok,
|
||||
)
|
||||
return False
|
||||
if not self.can_be_sold(unit_type):
|
||||
QMessageBox.critical(
|
||||
self,
|
||||
"Could not sell aircraft",
|
||||
f"Attempted to sell one {unit_type} at {self.cp.name} "
|
||||
"but none are available. Are all aircraft currently "
|
||||
"assigned to a mission?",
|
||||
QMessageBox.Ok,
|
||||
)
|
||||
return False
|
||||
|
||||
inventory = self.game_model.game.aircraft_inventory.for_control_point(self.cp)
|
||||
pending_deliveries = self.pending_deliveries.units.get(unit_type, 0)
|
||||
if pending_deliveries <= 0 < inventory.available(unit_type):
|
||||
inventory.remove_aircraft(unit_type, 1)
|
||||
|
||||
super().sell(unit_type)
|
||||
self.hangar_status.update_label()
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class Campaign:
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, path: Path) -> Campaign:
|
||||
with path.open() as campaign_file:
|
||||
with path.open(encoding="utf-8") as campaign_file:
|
||||
data = json.load(campaign_file)
|
||||
|
||||
sanitized_theater = data["theater"].replace(" ", "")
|
||||
|
||||
Reference in New Issue
Block a user