diff --git a/game/data/weapons.py b/game/data/weapons.py index 8d53f7f7..5562e99d 100644 --- a/game/data/weapons.py +++ b/game/data/weapons.py @@ -31,6 +31,16 @@ def weapons_migrator(name: str) -> str: return name +def weapons_migrator_lib(name: str) -> str: + # Splitting this from our own migrations + if "KH" in name: + return "Kh" + name[2:] + migration_map = {} + while name in migration_map: + name = migration_map[name] + return name + + @dataclass(frozen=True) class Weapon: """Wrapper for DCS weapons.""" @@ -153,7 +163,9 @@ class WeaponGroup: def __setstate__(self, state: dict[str, Any]) -> None: # Update any existing models with new data on load. - updated = WeaponGroup.named(weapons_migrator(state["name"])) + name = weapons_migrator(state["name"]) + name = weapons_migrator_lib(name) + updated = WeaponGroup.named(name) state.update(updated.__dict__) self.__dict__.update(state) diff --git a/game/migrator.py b/game/migrator.py index ffab971c..85eee9d4 100644 --- a/game/migrator.py +++ b/game/migrator.py @@ -1,5 +1,6 @@ from __future__ import annotations +from datetime import datetime from typing import TYPE_CHECKING, Any from dcs.countries import countries_by_name @@ -18,8 +19,9 @@ def try_set_attr(obj: Any, attr_name: str, val: Any = None) -> None: class Migrator: - def __init__(self, game: Game): + def __init__(self, game: Game, is_liberation: bool): self.game = game + self.is_liberation = is_liberation self._migrate_game() def _migrate_game(self) -> None: @@ -62,6 +64,10 @@ class Migrator: for p in c.ato.packages: try_set_attr(p, "custom_name") try_set_attr(p, "frequency") + if self.is_liberation and isinstance(p.time_over_target, datetime): + p.time_over_target = ( + p.time_over_target - self.game.conditions.start_time + ) def _update_control_points(self) -> None: for cp in self.game.theater.controlpoints: diff --git a/game/persistency.py b/game/persistency.py index 2ef07fe3..75ee427f 100644 --- a/game/persistency.py +++ b/game/persistency.py @@ -17,6 +17,11 @@ _dcs_saved_game_folder: Optional[str] = None # fmt: off +class DummyObject: + def __setstate__(self, state): + self.__dict__.update(state) + + class MigrationUnpickler(pickle.Unpickler): """Custom unpickler to migrate campaign save-files for when components have been moved""" def find_class(self, module: Any, name: str) -> Any: @@ -52,6 +57,8 @@ class MigrationUnpickler(pickle.Unpickler): return Thunderstorm if name == "Hipico": return dcs.terrain.falklands.airports.Hipico_Flying_Club + if name in ["SaveManager", "SaveGameBundle"]: + return DummyObject return super().find_class(module, name) # fmt: on diff --git a/qt_ui/windows/QLiberationWindow.py b/qt_ui/windows/QLiberationWindow.py index e1598fad..57aae6a2 100644 --- a/qt_ui/windows/QLiberationWindow.py +++ b/qt_ui/windows/QLiberationWindow.py @@ -326,7 +326,8 @@ class QLiberationWindow(QMainWindow): def migrate_game(self, game, path): if game: - Migrator(game) + is_liberation = ".liberation" in path + Migrator(game, is_liberation) else: relative_path = Path(path) QMessageBox.critical( diff --git a/resources/units/aircraft/Ka-50_3.yaml b/resources/units/aircraft/Ka-50_3.yaml index 6e0dc286..be6513fb 100644 --- a/resources/units/aircraft/Ka-50_3.yaml +++ b/resources/units/aircraft/Ka-50_3.yaml @@ -17,6 +17,7 @@ price: 20 role: Attack variants: Ka-50 Hokum III: {} + Ka-50 Hokum (Blackshark 3): {} # for compatibility with Liberation radios: intra_flight: R-800L1 inter_flight: R-800L1