mirror of
https://github.com/ModOrganizer2/modorganizer-basic_games.git
synced 2026-07-27 14:07:29 -07:00
95 lines
2.9 KiB
Python
95 lines
2.9 KiB
Python
# -*- encoding: utf-8 -*-
|
|
from pathlib import Path
|
|
from typing import List
|
|
|
|
from PyQt6.QtCore import QDir, QFileInfo
|
|
|
|
import mobase
|
|
|
|
from ..basic_game import BasicGame, BasicGameSaveGame
|
|
|
|
|
|
class Witcher1SaveGame(BasicGameSaveGame):
|
|
def __init__(self, filepath):
|
|
super().__init__(filepath)
|
|
self.areaName: str = ""
|
|
self.parseSaveFile(filepath)
|
|
|
|
@staticmethod
|
|
def readInt(fp, length=4) -> int:
|
|
return int.from_bytes(fp.read(length), "little")
|
|
|
|
@staticmethod
|
|
def readFixedString(fp, length) -> str:
|
|
b: bytes = fp.read(length)
|
|
res = b.decode("utf-16")
|
|
return res.rstrip("\0")
|
|
|
|
def parseSaveFile(self, filepath: Path):
|
|
# https://github.com/xoreos/xoreos/blob/82bd991052732ab1f8f75f512b3dfabfcc92ae8f/src/aurora/thewitchersavefile.cpp#L60
|
|
with filepath.open(mode="rb") as fp:
|
|
magic = fp.read(4)
|
|
if magic != b"RGMH":
|
|
raise ValueError("Invalid TheWitcherSave file!")
|
|
|
|
version = self.readInt(fp)
|
|
if version != 1:
|
|
raise ValueError("Invalid TheWitcherSave file!")
|
|
|
|
# TODO: get the preview image
|
|
# dataOffset = self.readInt(fp, 8)
|
|
fp.seek(8, 1)
|
|
fp.seek(8, 1)
|
|
fp.seek(4 * 4, 1)
|
|
|
|
lightningStorm = self.readFixedString(fp, 2048)
|
|
if lightningStorm != "Lightning Storm":
|
|
raise ValueError('Missing "Lightning Storm"')
|
|
|
|
areaName1 = self.readFixedString(fp, 2048)
|
|
areaName2 = self.readFixedString(fp, 2048)
|
|
|
|
if areaName1 != areaName2:
|
|
raise ValueError("Invalid Area Name!")
|
|
|
|
self.areaName = areaName1
|
|
|
|
def getName(self) -> str:
|
|
return self.areaName
|
|
|
|
|
|
class Witcher1Game(BasicGame):
|
|
Name = "Witcher 1 Support Plugin"
|
|
Author = "erri120"
|
|
Version = "1.0.0"
|
|
|
|
GameName = "The Witcher: Enhanced Edition"
|
|
GameShortName = "witcher"
|
|
GameNexusName = "witcher"
|
|
GameNexusId = 150
|
|
GameSteamId = 20900
|
|
GameGogId = 1207658924
|
|
GameBinary = "System/witcher.exe"
|
|
GameDataPath = "Data"
|
|
GameSaveExtension = "TheWitcherSave"
|
|
GameDocumentsDirectory = "%DOCUMENTS%/The Witcher"
|
|
GameSavesDirectory = "%GAME_DOCUMENTS%/saves"
|
|
GameSupportURL = (
|
|
r"https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/"
|
|
"Game:-The-Witcher"
|
|
)
|
|
|
|
def init(self, organizer: mobase.IOrganizer) -> bool:
|
|
super().init(organizer)
|
|
return True
|
|
|
|
def executables(self) -> List[mobase.ExecutableInfo]:
|
|
path = QFileInfo(self.gameDirectory(), "System/witcher.exe")
|
|
return [mobase.ExecutableInfo("The Witcher", path)]
|
|
|
|
def listSaves(self, folder: QDir) -> List[mobase.ISaveGame]:
|
|
return [
|
|
Witcher1SaveGame(path)
|
|
for path in Path(folder.absolutePath()).glob("*.TheWitcherSave")
|
|
]
|