mirror of
https://github.com/ModOrganizer2/modorganizer-basic_games.git
synced 2026-07-27 14:07:29 -07:00
Merge remote-tracking branch 'origin/master' into dev/vcpkg
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
- id: check-toml
|
||||
- id: check-merge-conflict
|
||||
- id: mixed-line-ending
|
||||
args: [--fix=lf]
|
||||
- id: check-case-conflict
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.11.7 # must match pyproject.toml
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--extend-select, I, --fix]
|
||||
- id: ruff-format
|
||||
|
||||
ci:
|
||||
autofix_commit_msg: "[pre-commit.ci] Auto fixes from pre-commit.com hooks."
|
||||
autofix_prs: true
|
||||
autoupdate_commit_msg: "[pre-commit.ci] Pre-commit autoupdate."
|
||||
autoupdate_schedule: quarterly
|
||||
submodules: false
|
||||
@@ -4,4 +4,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import mobase
|
||||
from PyQt6.QtCore import QDir
|
||||
|
||||
import mobase
|
||||
|
||||
|
||||
class BasicLocalSavegames(mobase.LocalSavegames):
|
||||
def __init__(self, game_save_dir: QDir):
|
||||
|
||||
@@ -78,7 +78,7 @@ class GlobPatterns:
|
||||
unfold: list[str] | None = None
|
||||
valid: list[str] | None = None
|
||||
delete: list[str] | None = None
|
||||
move: dict[str, str] = field(default_factory=dict)
|
||||
move: dict[str, str] = field(default_factory=dict[str, str])
|
||||
|
||||
def merge(
|
||||
self, other: GlobPatterns, mode: Literal["merge", "replace"] = "replace"
|
||||
|
||||
@@ -6,11 +6,12 @@ from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Self, Sequence
|
||||
|
||||
import mobase
|
||||
from PyQt6.QtCore import QDateTime, QLocale, Qt
|
||||
from PyQt6.QtGui import QImage, QPixmap
|
||||
from PyQt6.QtWidgets import QFormLayout, QLabel, QSizePolicy, QVBoxLayout, QWidget
|
||||
|
||||
import mobase
|
||||
|
||||
|
||||
def format_date(date_time: QDateTime | datetime | str, format_str: str | None = None):
|
||||
"""Default format for date and time in the `BasicGameSaveGameInfoWidget`.
|
||||
|
||||
+16
-3
@@ -5,9 +5,11 @@ import sys
|
||||
from pathlib import Path
|
||||
from typing import Callable, Generic, TypeVar
|
||||
|
||||
import mobase
|
||||
from PyQt6.QtCore import QDir, QFileInfo, QStandardPaths
|
||||
from PyQt6.QtGui import QIcon
|
||||
from PyQt6.QtWidgets import QMessageBox
|
||||
|
||||
import mobase
|
||||
|
||||
from .basic_features.basic_save_game_info import (
|
||||
BasicGameSaveGame,
|
||||
@@ -380,11 +382,22 @@ class BasicGame(mobase.IPluginGame):
|
||||
from .origin_utils import find_games as find_origin_games
|
||||
from .steam_utils import find_games as find_steam_games
|
||||
|
||||
errors: list[tuple[str, Exception]] = []
|
||||
BasicGame.steam_games = find_steam_games()
|
||||
BasicGame.gog_games = find_gog_games()
|
||||
BasicGame.origin_games = find_origin_games()
|
||||
BasicGame.epic_games = find_epic_games()
|
||||
BasicGame.eadesktop_games = find_eadesktop_games()
|
||||
BasicGame.epic_games = find_epic_games(errors)
|
||||
BasicGame.eadesktop_games = find_eadesktop_games(errors)
|
||||
|
||||
if errors:
|
||||
QMessageBox.critical(
|
||||
None,
|
||||
"Errors loading game list",
|
||||
(
|
||||
"The following errors occurred while loading the list of available games:\n"
|
||||
f"\n- {'\n\n- '.join('\n '.join(str(e) for e in messageError) for messageError in errors)}"
|
||||
),
|
||||
)
|
||||
|
||||
# File containing the plugin:
|
||||
_fromName: str
|
||||
|
||||
+13
-2
@@ -2,13 +2,14 @@
|
||||
|
||||
import configparser
|
||||
import os
|
||||
import sys
|
||||
import xml.etree.ElementTree as et
|
||||
from configparser import NoOptionError
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
|
||||
def find_games() -> Dict[str, Path]:
|
||||
def find_games(errors: list[tuple[str, Exception]] | None = None) -> Dict[str, Path]:
|
||||
"""
|
||||
Find the list of EA Desktop games installed.
|
||||
|
||||
@@ -37,7 +38,17 @@ def find_games() -> Dict[str, Path]:
|
||||
ini_content = "[mod_organizer]\n" + f.read()
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read_string(ini_content)
|
||||
try:
|
||||
config.read_string(ini_content)
|
||||
except configparser.ParsingError as e:
|
||||
error_message = (
|
||||
f'Failed to parse EA Desktop games list file "{user_ini}",\n'
|
||||
" Try to run the launcher to recreate it."
|
||||
)
|
||||
print(error_message, e, file=sys.stderr)
|
||||
if errors is not None:
|
||||
errors.append((error_message, e))
|
||||
return games
|
||||
|
||||
try:
|
||||
install_path = Path(config.get("mod_organizer", "user.downloadinplacedir"))
|
||||
|
||||
+36
-12
@@ -9,8 +9,12 @@ import winreg
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
|
||||
ErrorList = list[tuple[str, Exception]]
|
||||
|
||||
def find_epic_games() -> Iterable[tuple[str, Path]]:
|
||||
|
||||
def find_epic_games(
|
||||
errors: ErrorList | None = None,
|
||||
) -> Iterable[tuple[str, Path]]:
|
||||
try:
|
||||
with winreg.OpenKey(
|
||||
winreg.HKEY_LOCAL_MACHINE,
|
||||
@@ -30,15 +34,23 @@ def find_epic_games() -> Iterable[tuple[str, Path]]:
|
||||
manifest_file_data["AppName"],
|
||||
Path(manifest_file_data["InstallLocation"]),
|
||||
)
|
||||
except (json.JSONDecodeError, KeyError):
|
||||
except (json.JSONDecodeError, KeyError) as e:
|
||||
error_message = (
|
||||
f'Unable to parse Epic Games manifest file: "{manifest_file_path}"\n'
|
||||
" Try to run the launcher recreate it."
|
||||
)
|
||||
print(
|
||||
"Unable to parse Epic Games manifest file",
|
||||
manifest_file_path,
|
||||
error_message,
|
||||
e,
|
||||
file=sys.stderr,
|
||||
)
|
||||
if errors is not None:
|
||||
errors.append((error_message, e))
|
||||
|
||||
|
||||
def find_legendary_games(config_path: str | None = None) -> Iterable[tuple[str, Path]]:
|
||||
def find_legendary_games(
|
||||
config_path: str | None = None, errors: ErrorList | None = None
|
||||
) -> Iterable[tuple[str, Path]]:
|
||||
# Based on legendary source:
|
||||
# https://github.com/derrod/legendary/blob/master/legendary/lfs/lgndry.py
|
||||
if config_path := config_path or os.environ.get("XDG_CONFIG_HOME"):
|
||||
@@ -53,21 +65,33 @@ def find_legendary_games(config_path: str | None = None) -> Iterable[tuple[str,
|
||||
installed_games = json.load(installed_file)
|
||||
for game in installed_games.values():
|
||||
yield game["app_name"], Path(game["install_path"])
|
||||
except (json.JSONDecodeError, AttributeError, KeyError):
|
||||
except (json.JSONDecodeError, AttributeError, KeyError) as e:
|
||||
error_message = (
|
||||
f'Unable to parse installed games from Legendary/Heroic launcher: "{installed_path}"\n'
|
||||
" Try to run the launcher to recrated the file."
|
||||
)
|
||||
print(
|
||||
"Unable to parse installed games from Legendary",
|
||||
installed_path,
|
||||
error_message,
|
||||
e,
|
||||
file=sys.stderr,
|
||||
)
|
||||
if errors is not None:
|
||||
errors.append((error_message, e))
|
||||
|
||||
|
||||
def find_heroic_games():
|
||||
return find_legendary_games(os.path.expandvars(r"%AppData%\heroic\legendaryConfig"))
|
||||
def find_heroic_games(errors: ErrorList | None = None):
|
||||
return find_legendary_games(
|
||||
os.path.expandvars(r"%AppData%\heroic\legendaryConfig"), errors
|
||||
)
|
||||
|
||||
|
||||
def find_games() -> dict[str, Path]:
|
||||
def find_games(errors: ErrorList | None = None) -> dict[str, Path]:
|
||||
return dict(
|
||||
itertools.chain(find_epic_games(), find_legendary_games(), find_heroic_games())
|
||||
itertools.chain(
|
||||
find_epic_games(errors=errors),
|
||||
find_legendary_games(errors=errors),
|
||||
find_heroic_games(errors=errors),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
+87
-86
@@ -1,86 +1,87 @@
|
||||
import mobase
|
||||
from PyQt6.QtCore import QDir, QFileInfo
|
||||
|
||||
from ..basic_features import BasicLocalSavegames
|
||||
from ..basic_game import BasicGame
|
||||
from ..steam_utils import find_steam_path
|
||||
|
||||
|
||||
# Lifted from https://github.com/ModOrganizer2/modorganizer-basic_games/blob/71dbb8c557d43cba9d290674a332e7ecd1650261/games/game_darkestdungeon.py
|
||||
class ArkhamCityModDataChecker(mobase.ModDataChecker):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.validDirNames = [
|
||||
"config",
|
||||
"cookedpcconsole",
|
||||
"localization",
|
||||
"movies",
|
||||
"moviesstereo",
|
||||
"splash",
|
||||
]
|
||||
|
||||
def dataLooksValid(
|
||||
self, filetree: mobase.IFileTree
|
||||
) -> mobase.ModDataChecker.CheckReturn:
|
||||
for entry in filetree:
|
||||
if not entry.isDir():
|
||||
continue
|
||||
if entry.name().casefold() in self.validDirNames:
|
||||
return mobase.ModDataChecker.VALID
|
||||
return mobase.ModDataChecker.INVALID
|
||||
|
||||
|
||||
class ArkhamCityGame(BasicGame):
|
||||
Name = "Batman: Arkham City Plugin"
|
||||
Author = "Paynamia"
|
||||
Version = "0.5.3"
|
||||
|
||||
GameName = "Batman: Arkham City"
|
||||
GameShortName = "batmanarkhamcity"
|
||||
GameNexusId = 372
|
||||
GameSteamId = 200260
|
||||
GameGogId = 1260066469
|
||||
GameEpicId = "Egret"
|
||||
GameBinary = "Binaries/Win32/BatmanAC.exe"
|
||||
GameLauncher = "Binaries/Win32/BmLauncher.exe"
|
||||
GameDataPath = "BmGame"
|
||||
GameDocumentsDirectory = (
|
||||
"%DOCUMENTS%/WB Games/Batman Arkham City GOTY/BmGame/Config"
|
||||
)
|
||||
GameIniFiles = ["UserEngine.ini", "UserGame.ini", "UserInput.ini"]
|
||||
GameSaveExtension = "sgd"
|
||||
|
||||
# This will only detect saves from the earliest-created Steam profile on the user's PC.
|
||||
def savesDirectory(self) -> QDir:
|
||||
docSaves = QDir(self.documentsDirectory().cleanPath("../../SaveData"))
|
||||
if self.is_steam():
|
||||
if (steamDir := find_steam_path()) is None:
|
||||
return docSaves
|
||||
for child in steamDir.joinpath("userdata").iterdir():
|
||||
if not child.is_dir() or child.name == "0":
|
||||
continue
|
||||
steamSaves = child.joinpath("200260", "remote")
|
||||
if steamSaves.is_dir():
|
||||
return QDir(str(steamSaves))
|
||||
else:
|
||||
return docSaves
|
||||
else:
|
||||
return docSaves
|
||||
|
||||
def init(self, organizer: mobase.IOrganizer) -> bool:
|
||||
super().init(organizer)
|
||||
self._register_feature(ArkhamCityModDataChecker())
|
||||
self._register_feature(BasicLocalSavegames(self.savesDirectory()))
|
||||
return True
|
||||
|
||||
def executables(self):
|
||||
return [
|
||||
mobase.ExecutableInfo(
|
||||
"Batman: Arkham City",
|
||||
QFileInfo(self.gameDirectory(), "Binaries/Win32/BatmanAC.exe"),
|
||||
),
|
||||
mobase.ExecutableInfo(
|
||||
"Arkham City Launcher",
|
||||
QFileInfo(self.gameDirectory(), "Binaries/Win32/BmLauncher.exe"),
|
||||
),
|
||||
]
|
||||
from PyQt6.QtCore import QDir, QFileInfo
|
||||
|
||||
import mobase
|
||||
|
||||
from ..basic_features import BasicLocalSavegames
|
||||
from ..basic_game import BasicGame
|
||||
from ..steam_utils import find_steam_path
|
||||
|
||||
|
||||
# Lifted from https://github.com/ModOrganizer2/modorganizer-basic_games/blob/71dbb8c557d43cba9d290674a332e7ecd1650261/games/game_darkestdungeon.py
|
||||
class ArkhamCityModDataChecker(mobase.ModDataChecker):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.validDirNames = [
|
||||
"config",
|
||||
"cookedpcconsole",
|
||||
"localization",
|
||||
"movies",
|
||||
"moviesstereo",
|
||||
"splash",
|
||||
]
|
||||
|
||||
def dataLooksValid(
|
||||
self, filetree: mobase.IFileTree
|
||||
) -> mobase.ModDataChecker.CheckReturn:
|
||||
for entry in filetree:
|
||||
if not entry.isDir():
|
||||
continue
|
||||
if entry.name().casefold() in self.validDirNames:
|
||||
return mobase.ModDataChecker.VALID
|
||||
return mobase.ModDataChecker.INVALID
|
||||
|
||||
|
||||
class ArkhamCityGame(BasicGame):
|
||||
Name = "Batman: Arkham City Plugin"
|
||||
Author = "Paynamia"
|
||||
Version = "0.5.3"
|
||||
|
||||
GameName = "Batman: Arkham City"
|
||||
GameShortName = "batmanarkhamcity"
|
||||
GameNexusId = 372
|
||||
GameSteamId = 200260
|
||||
GameGogId = 1260066469
|
||||
GameEpicId = "Egret"
|
||||
GameBinary = "Binaries/Win32/BatmanAC.exe"
|
||||
GameLauncher = "Binaries/Win32/BmLauncher.exe"
|
||||
GameDataPath = "BmGame"
|
||||
GameDocumentsDirectory = (
|
||||
"%DOCUMENTS%/WB Games/Batman Arkham City GOTY/BmGame/Config"
|
||||
)
|
||||
GameIniFiles = ["UserEngine.ini", "UserGame.ini", "UserInput.ini"]
|
||||
GameSaveExtension = "sgd"
|
||||
|
||||
# This will only detect saves from the earliest-created Steam profile on the user's PC.
|
||||
def savesDirectory(self) -> QDir:
|
||||
docSaves = QDir(self.documentsDirectory().cleanPath("../../SaveData"))
|
||||
if self.is_steam():
|
||||
if (steamDir := find_steam_path()) is None:
|
||||
return docSaves
|
||||
for child in steamDir.joinpath("userdata").iterdir():
|
||||
if not child.is_dir() or child.name == "0":
|
||||
continue
|
||||
steamSaves = child.joinpath("200260", "remote")
|
||||
if steamSaves.is_dir():
|
||||
return QDir(str(steamSaves))
|
||||
else:
|
||||
return docSaves
|
||||
else:
|
||||
return docSaves
|
||||
|
||||
def init(self, organizer: mobase.IOrganizer) -> bool:
|
||||
super().init(organizer)
|
||||
self._register_feature(ArkhamCityModDataChecker())
|
||||
self._register_feature(BasicLocalSavegames(self.savesDirectory()))
|
||||
return True
|
||||
|
||||
def executables(self):
|
||||
return [
|
||||
mobase.ExecutableInfo(
|
||||
"Batman: Arkham City",
|
||||
QFileInfo(self.gameDirectory(), "Binaries/Win32/BatmanAC.exe"),
|
||||
),
|
||||
mobase.ExecutableInfo(
|
||||
"Arkham City Launcher",
|
||||
QFileInfo(self.gameDirectory(), "Binaries/Win32/BmLauncher.exe"),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -6,9 +6,10 @@ from collections.abc import Mapping
|
||||
from pathlib import Path
|
||||
from typing import BinaryIO
|
||||
|
||||
import mobase
|
||||
from PyQt6.QtCore import QDateTime, QDir, QFile, QFileInfo
|
||||
|
||||
import mobase
|
||||
|
||||
from ..basic_features import BasicLocalSavegames
|
||||
from ..basic_features.basic_save_game_info import (
|
||||
BasicGameSaveGame,
|
||||
|
||||
@@ -2,9 +2,10 @@ import json
|
||||
from collections.abc import Mapping
|
||||
from pathlib import Path
|
||||
|
||||
import mobase
|
||||
from PyQt6.QtCore import QDateTime, QDir
|
||||
|
||||
import mobase
|
||||
|
||||
from ..basic_features.basic_save_game_info import (
|
||||
BasicGameSaveGame,
|
||||
BasicGameSaveGameInfo,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import mobase
|
||||
from PyQt6.QtCore import QFileInfo
|
||||
|
||||
import mobase
|
||||
|
||||
from ..basic_game import BasicGame
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, Literal, TypeVar
|
||||
|
||||
import mobase
|
||||
from PyQt6.QtCore import QDateTime, QDir, Qt, qCritical, qInfo, qWarning
|
||||
from PyQt6.QtWidgets import (
|
||||
QCheckBox,
|
||||
@@ -20,6 +19,8 @@ from PyQt6.QtWidgets import (
|
||||
QWidget,
|
||||
)
|
||||
|
||||
import mobase
|
||||
|
||||
from ..basic_features import BasicLocalSavegames, BasicModDataChecker, GlobPatterns
|
||||
from ..basic_features.basic_save_game_info import (
|
||||
BasicGameSaveGame,
|
||||
@@ -74,7 +75,7 @@ def parse_cyberpunk_save_metadata(save_path: Path, save: mobase.ISaveGame):
|
||||
"Street Cred": int(meta_data["streetCred"]),
|
||||
"Life Path": meta_data["lifePath"],
|
||||
"Difficulty": meta_data["difficulty"],
|
||||
"Gender": f'{meta_data["bodyGender"]} / {meta_data["brainGender"]}',
|
||||
"Gender": f"{meta_data['bodyGender']} / {meta_data['brainGender']}",
|
||||
"Game version": meta_data["buildPatch"],
|
||||
}
|
||||
except (FileNotFoundError, json.JSONDecodeError):
|
||||
@@ -487,7 +488,7 @@ class Cyberpunk2077Game(BasicGame):
|
||||
_,
|
||||
) = self._modlist_files.update_modlist("redmod")
|
||||
modlist_param = f'-modlist="{modlist_path}"' if modlist else ""
|
||||
args = f"{args[:m.start()]}{modlist_param}{args[m.end():]}"
|
||||
args = f"{args[: m.start()]}{modlist_param}{args[m.end() :]}"
|
||||
qInfo(f"Manual modlist deployment: replacing {m[0]}, new args = {args}")
|
||||
self._check_redmod_result(
|
||||
self._organizer.waitForApplication(
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
import mobase
|
||||
|
||||
from ..basic_game import BasicGame
|
||||
|
||||
|
||||
class DaggerfallUnityModDataChecker(mobase.ModDataChecker):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.validDirNames = [
|
||||
"biogs",
|
||||
"docs",
|
||||
"factions",
|
||||
"fonts",
|
||||
"mods",
|
||||
"questpacks",
|
||||
"quests",
|
||||
"sound",
|
||||
"soundfonts",
|
||||
"spellicons",
|
||||
"tables",
|
||||
"text",
|
||||
"textures",
|
||||
"worlddata",
|
||||
"aa",
|
||||
]
|
||||
|
||||
def dataLooksValid(
|
||||
self, filetree: mobase.IFileTree
|
||||
) -> mobase.ModDataChecker.CheckReturn:
|
||||
for entry in filetree:
|
||||
if not entry.isDir():
|
||||
continue
|
||||
if entry.name().casefold() in self.validDirNames:
|
||||
return mobase.ModDataChecker.VALID
|
||||
return mobase.ModDataChecker.INVALID
|
||||
|
||||
|
||||
class DaggerfallUnityGame(BasicGame):
|
||||
def init(self, organizer: mobase.IOrganizer) -> bool:
|
||||
super().init(organizer)
|
||||
self._register_feature(DaggerfallUnityModDataChecker())
|
||||
return True
|
||||
|
||||
Name = "Daggerfall Unity Support Plugin"
|
||||
Author = "HomerSimpleton"
|
||||
Version = "1.0.0"
|
||||
|
||||
GameName = "Daggerfall Unity"
|
||||
GameShortName = "daggerfallunity"
|
||||
GameBinary = "DaggerfallUnity.exe"
|
||||
GameLauncher = "DaggerfallUnity.exe"
|
||||
GameDataPath = "%GAME_PATH%/DaggerfallUnity_Data/StreamingAssets"
|
||||
GameSupportURL = (
|
||||
r"https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/"
|
||||
"Game:-Daggerfall-Unity"
|
||||
)
|
||||
import mobase
|
||||
|
||||
from ..basic_game import BasicGame
|
||||
|
||||
|
||||
class DaggerfallUnityModDataChecker(mobase.ModDataChecker):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.validDirNames = [
|
||||
"biogs",
|
||||
"docs",
|
||||
"factions",
|
||||
"fonts",
|
||||
"mods",
|
||||
"questpacks",
|
||||
"quests",
|
||||
"sound",
|
||||
"soundfonts",
|
||||
"spellicons",
|
||||
"tables",
|
||||
"text",
|
||||
"textures",
|
||||
"worlddata",
|
||||
"aa",
|
||||
]
|
||||
|
||||
def dataLooksValid(
|
||||
self, filetree: mobase.IFileTree
|
||||
) -> mobase.ModDataChecker.CheckReturn:
|
||||
for entry in filetree:
|
||||
if not entry.isDir():
|
||||
continue
|
||||
if entry.name().casefold() in self.validDirNames:
|
||||
return mobase.ModDataChecker.VALID
|
||||
return mobase.ModDataChecker.INVALID
|
||||
|
||||
|
||||
class DaggerfallUnityGame(BasicGame):
|
||||
def init(self, organizer: mobase.IOrganizer) -> bool:
|
||||
super().init(organizer)
|
||||
self._register_feature(DaggerfallUnityModDataChecker())
|
||||
return True
|
||||
|
||||
Name = "Daggerfall Unity Support Plugin"
|
||||
Author = "HomerSimpleton"
|
||||
Version = "1.0.0"
|
||||
|
||||
GameName = "Daggerfall Unity"
|
||||
GameShortName = "daggerfallunity"
|
||||
GameBinary = "DaggerfallUnity.exe"
|
||||
GameLauncher = "DaggerfallUnity.exe"
|
||||
GameDataPath = "%GAME_PATH%/DaggerfallUnity_Data/StreamingAssets"
|
||||
GameSupportURL = (
|
||||
r"https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/"
|
||||
"Game:-Daggerfall-Unity"
|
||||
)
|
||||
|
||||
+31
-31
@@ -1,31 +1,31 @@
|
||||
import mobase
|
||||
|
||||
from ..basic_features import BasicGameSaveGameInfo
|
||||
from ..basic_game import BasicGame
|
||||
|
||||
|
||||
class DAOriginsGame(BasicGame):
|
||||
Name = "Dragon Age Origins Support Plugin"
|
||||
Author = "Patchier"
|
||||
Version = "1.1.1"
|
||||
|
||||
GameName = "Dragon Age: Origins"
|
||||
GameShortName = "dragonage"
|
||||
GameBinary = r"bin_ship\DAOrigins.exe"
|
||||
GameDataPath = r"%DOCUMENTS%\BioWare\Dragon Age\packages\core\override"
|
||||
GameSavesDirectory = r"%DOCUMENTS%\BioWare\Dragon Age\Characters"
|
||||
GameSaveExtension = "das"
|
||||
GameSteamId = [17450, 47810]
|
||||
GameGogId = 1949616134
|
||||
GameEaDesktopId = [70377, 70843]
|
||||
GameSupportURL = (
|
||||
r"https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/"
|
||||
"Game:-Dragon-Age:-Origins"
|
||||
)
|
||||
|
||||
def init(self, organizer: mobase.IOrganizer):
|
||||
super().init(organizer)
|
||||
self._register_feature(
|
||||
BasicGameSaveGameInfo(lambda s: s.parent.joinpath("screen.dds"))
|
||||
)
|
||||
return True
|
||||
import mobase
|
||||
|
||||
from ..basic_features import BasicGameSaveGameInfo
|
||||
from ..basic_game import BasicGame
|
||||
|
||||
|
||||
class DAOriginsGame(BasicGame):
|
||||
Name = "Dragon Age Origins Support Plugin"
|
||||
Author = "Patchier"
|
||||
Version = "1.1.1"
|
||||
|
||||
GameName = "Dragon Age: Origins"
|
||||
GameShortName = "dragonage"
|
||||
GameBinary = r"bin_ship\DAOrigins.exe"
|
||||
GameDataPath = r"%DOCUMENTS%\BioWare\Dragon Age\packages\core\override"
|
||||
GameSavesDirectory = r"%DOCUMENTS%\BioWare\Dragon Age\Characters"
|
||||
GameSaveExtension = "das"
|
||||
GameSteamId = [17450, 47810]
|
||||
GameGogId = 1949616134
|
||||
GameEaDesktopId = [70377, 70843]
|
||||
GameSupportURL = (
|
||||
r"https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/"
|
||||
"Game:-Dragon-Age:-Origins"
|
||||
)
|
||||
|
||||
def init(self, organizer: mobase.IOrganizer):
|
||||
super().init(organizer)
|
||||
self._register_feature(
|
||||
BasicGameSaveGameInfo(lambda s: s.parent.joinpath("screen.dds"))
|
||||
)
|
||||
return True
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import mobase
|
||||
from PyQt6.QtCore import QDir, QFileInfo, QStandardPaths
|
||||
|
||||
import mobase
|
||||
|
||||
from ..basic_game import BasicGame, BasicGameSaveGame
|
||||
from ..steam_utils import find_steam_path
|
||||
|
||||
@@ -166,7 +167,7 @@ class DarkestDungeonGame(BasicGame):
|
||||
GameNexusId = 804
|
||||
GameSteamId = 262060
|
||||
GameGogId = 1719198803
|
||||
GameBinary = "_windowsnosteam//darkest.exe"
|
||||
GameBinary = "_windowsnosteam/win64/darkest.exe"
|
||||
GameDataPath = ""
|
||||
GameSupportURL = (
|
||||
r"https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/"
|
||||
@@ -180,9 +181,9 @@ class DarkestDungeonGame(BasicGame):
|
||||
|
||||
def executables(self):
|
||||
if self.is_steam():
|
||||
path = QFileInfo(self.gameDirectory(), "_windows/darkest.exe")
|
||||
path = QFileInfo(self.gameDirectory(), "_windows/win64/darkest.exe")
|
||||
else:
|
||||
path = QFileInfo(self.gameDirectory(), "_windowsnosteam/darkest.exe")
|
||||
path = QFileInfo(self.gameDirectory(), "_windowsnosteam/win64/darkest.exe")
|
||||
return [
|
||||
mobase.ExecutableInfo("Darkest Dungeon", path).withWorkingDirectory(
|
||||
self.gameDirectory()
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import struct
|
||||
from pathlib import Path
|
||||
|
||||
import mobase
|
||||
from PyQt6.QtGui import QImage
|
||||
|
||||
import mobase
|
||||
|
||||
from ..basic_features import BasicGameSaveGameInfo
|
||||
from ..basic_game import BasicGame
|
||||
|
||||
|
||||
@@ -69,8 +69,7 @@ class DivinityOriginalSinEnhancedEditionGame(BasicGame, mobase.IPluginFileMapper
|
||||
GameDataPath = "Data"
|
||||
GameSaveExtension = "lsv"
|
||||
GameDocumentsDirectory = (
|
||||
"%USERPROFILE%/Documents/Larian Studios/"
|
||||
"Divinity Original Sin Enhanced Edition"
|
||||
"%USERPROFILE%/Documents/Larian Studios/Divinity Original Sin Enhanced Edition"
|
||||
)
|
||||
GameSavesDirectory = (
|
||||
"%USERPROFILE%/Documents/Larian Studios/"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import mobase
|
||||
from PyQt6.QtCore import QFileInfo
|
||||
|
||||
import mobase
|
||||
|
||||
from ..basic_game import BasicGame
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import mobase
|
||||
from PyQt6.QtCore import QFileInfo
|
||||
|
||||
import mobase
|
||||
|
||||
from ..basic_game import BasicGame
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user