Files

294 lines
9.9 KiB
Python
Raw Permalink Normal View History

2022-04-21 22:13:00 +02:00
from enum import IntEnum
2021-03-02 17:34:19 -06:00
from pathlib import Path
2020-06-17 16:54:27 -05:00
from PyQt6.QtCore import QDir, QFileInfo, Qt
from PyQt6.QtWidgets import QLabel, QVBoxLayout, QWidget
2020-06-17 16:54:27 -05:00
2025-04-25 08:23:10 +02:00
import mobase
2021-09-30 02:34:07 -05:00
from ..basic_features.basic_save_game_info import (
BasicGameSaveGame,
BasicGameSaveGameInfo,
)
2021-07-18 10:33:08 +02:00
from ..basic_game import BasicGame
2021-09-30 23:35:32 -05:00
from .stalkeranomaly import XRSave
2020-10-31 17:46:18 +01:00
2020-09-23 19:00:18 -05:00
class StalkerAnomalyModDataChecker(mobase.ModDataChecker):
_valid_folders: list[str] = [
2020-11-07 01:56:29 -06:00
"appdata",
2021-09-23 18:18:11 -05:00
"bin",
"db",
2020-11-07 01:56:29 -06:00
"gamedata",
]
2021-09-23 18:18:11 -05:00
def hasValidFolders(self, tree: mobase.IFileTree) -> bool:
2020-11-07 01:56:29 -06:00
for e in tree:
if e.isDir():
if e.name().lower() in self._valid_folders:
2021-09-23 18:18:11 -05:00
return True
return False
def findLostData(self, tree: mobase.IFileTree) -> list[mobase.FileTreeEntry]:
lost_db: list[mobase.FileTreeEntry] = []
2021-09-23 18:18:11 -05:00
for e in tree:
if e.isFile():
if e.suffix().lower().startswith("db"):
lost_db.append(e)
return lost_db
def dataLooksValid(
self, filetree: mobase.IFileTree
2021-09-23 18:18:11 -05:00
) -> mobase.ModDataChecker.CheckReturn:
if self.hasValidFolders(filetree):
2021-09-23 18:18:11 -05:00
return mobase.ModDataChecker.VALID
if self.findLostData(filetree):
2021-09-23 18:18:11 -05:00
return mobase.ModDataChecker.FIXABLE
2020-11-07 01:56:29 -06:00
return mobase.ModDataChecker.INVALID
2020-09-23 19:00:18 -05:00
def fix(self, filetree: mobase.IFileTree) -> mobase.IFileTree:
lost_db = self.findLostData(filetree)
2021-09-23 18:18:11 -05:00
if lost_db:
rfolder = filetree.addDirectory("db").addDirectory("mods")
2021-09-23 18:18:11 -05:00
for r in lost_db:
rfolder.insert(r, mobase.IFileTree.REPLACE)
return filetree
2021-09-23 18:18:11 -05:00
class Content(IntEnum):
INTERFACE = 0
TEXTURE = 1
MESH = 2
SCRIPT = 3
SOUND = 4
MCM = 5
CONFIG = 6
class StalkerAnomalyModDataContent(mobase.ModDataContent):
content: list[int] = []
2021-09-23 18:18:11 -05:00
def getAllContents(self) -> list[mobase.ModDataContent.Content]:
2021-09-23 18:18:11 -05:00
return [
mobase.ModDataContent.Content(
Content.INTERFACE, "Interface", ":/MO/gui/content/interface"
),
mobase.ModDataContent.Content(
Content.TEXTURE, "Textures", ":/MO/gui/content/texture"
),
mobase.ModDataContent.Content(
Content.MESH, "Meshes", ":/MO/gui/content/mesh"
),
mobase.ModDataContent.Content(
Content.SCRIPT, "Scripts", ":/MO/gui/content/script"
),
mobase.ModDataContent.Content(
Content.SOUND, "Sounds", ":/MO/gui/content/sound"
),
mobase.ModDataContent.Content(Content.MCM, "MCM", ":/MO/gui/content/menu"),
mobase.ModDataContent.Content(
Content.CONFIG, "Configs", ":/MO/gui/content/inifile"
),
]
def walkContent(
self, path: str, entry: mobase.FileTreeEntry
) -> mobase.IFileTree.WalkReturn:
name = entry.name().lower()
if entry.isFile():
ext = entry.suffix().lower()
if ext in ["dds", "thm"]:
self.content.append(Content.TEXTURE)
if path.startswith("gamedata/textures/ui"):
self.content.append(Content.INTERFACE)
elif ext in ["omf", "ogf"]:
self.content.append(Content.MESH)
elif ext in ["script"]:
self.content.append(Content.SCRIPT)
if "_mcm" in name:
self.content.append(Content.MCM)
elif ext in ["ogg"]:
self.content.append(Content.SOUND)
elif ext in ["ltx", "xml"]:
self.content.append(Content.CONFIG)
if path.startswith("gamedata/configs/ui"):
self.content.append(Content.INTERFACE)
return mobase.IFileTree.WalkReturn.CONTINUE
def getContentsFor(self, filetree: mobase.IFileTree) -> list[int]:
2021-09-23 18:18:11 -05:00
self.content = []
filetree.walk(self.walkContent, "/")
2021-09-23 18:18:11 -05:00
return self.content
2020-10-31 17:46:18 +01:00
2021-03-02 17:34:19 -06:00
class StalkerAnomalySaveGame(BasicGameSaveGame):
2021-09-30 23:35:32 -05:00
_filepath: Path
2021-09-30 02:34:07 -05:00
2021-09-30 23:35:32 -05:00
xr_save: XRSave
2021-09-30 02:34:07 -05:00
def __init__(self, filepath: Path):
super().__init__(filepath)
self._filepath = filepath
2021-09-30 23:35:32 -05:00
self.xr_save = XRSave(self._filepath)
2021-09-30 02:34:07 -05:00
def getName(self) -> str:
2021-09-30 23:35:32 -05:00
xr_save = self.xr_save
player = xr_save.player
2021-09-30 02:34:07 -05:00
if player:
name = player.character_name_str
2021-09-30 23:35:32 -05:00
time = xr_save.time_fmt
return f"{name}, {xr_save.save_fmt} [{time}]"
2021-09-30 02:34:07 -05:00
return ""
def allFiles(self) -> list[str]:
2021-09-30 02:34:07 -05:00
filepath = str(self._filepath)
paths = [filepath]
scoc = filepath.replace(".scop", ".scoc")
if Path(scoc).exists():
paths.append(scoc)
dds = filepath.replace(".scop", ".dds")
if Path(dds).exists():
paths.append(dds)
return paths
class StalkerAnomalySaveGameInfoWidget(mobase.ISaveGameInfoWidget):
def __init__(self, parent: QWidget | None):
2021-09-30 02:34:07 -05:00
super().__init__(parent)
layout = QVBoxLayout()
self._labelSave = self.newLabel(layout)
self._labelName = self.newLabel(layout)
self._labelFaction = self.newLabel(layout)
self._labelHealth = self.newLabel(layout)
self._labelMoney = self.newLabel(layout)
self._labelRank = self.newLabel(layout)
2021-09-30 23:35:32 -05:00
self._labelRep = self.newLabel(layout)
2021-09-30 02:34:07 -05:00
self.setLayout(layout)
palette = self.palette()
2022-04-21 22:13:00 +02:00
palette.setColor(self.backgroundRole(), Qt.GlobalColor.black)
2021-09-30 02:34:07 -05:00
self.setAutoFillBackground(True)
self.setPalette(palette)
2022-04-21 22:13:00 +02:00
self.setWindowFlags(
Qt.WindowType.ToolTip | Qt.WindowType.BypassGraphicsProxyWidget
)
2021-09-30 02:34:07 -05:00
def newLabel(self, layout: QVBoxLayout) -> QLabel:
label = QLabel()
2022-04-21 22:13:00 +02:00
label.setAlignment(Qt.AlignmentFlag.AlignLeft)
2021-09-30 02:34:07 -05:00
palette = label.palette()
2022-04-21 22:13:00 +02:00
palette.setColor(label.foregroundRole(), Qt.GlobalColor.white)
2021-09-30 02:34:07 -05:00
label.setPalette(palette)
layout.addWidget(label)
layout.addStretch()
return label
def setSave(self, save: mobase.ISaveGame):
self.resize(240, 32)
if not isinstance(save, StalkerAnomalySaveGame):
return
2021-09-30 23:35:32 -05:00
xr_save = save.xr_save
player = xr_save.player
2021-09-30 02:34:07 -05:00
if player:
2021-09-30 23:35:32 -05:00
self._labelSave.setText(f"Save: {xr_save.save_fmt}")
2021-09-30 02:34:07 -05:00
self._labelName.setText(f"Name: {player.character_name_str}")
2021-09-30 23:35:32 -05:00
self._labelFaction.setText(f"Faction: {xr_save.getFaction()}")
2021-09-30 02:34:07 -05:00
self._labelHealth.setText(f"Health: {player.health:.2f}%")
self._labelMoney.setText(f"Money: {player.money} RU")
2021-09-30 23:35:32 -05:00
self._labelRank.setText(f"Rank: {xr_save.getRank()} ({player.rank})")
self._labelRep.setText(
f"Reputation: {xr_save.getReputation()} ({player.reputation})"
)
2021-09-30 02:34:07 -05:00
class StalkerAnomalySaveGameInfo(BasicGameSaveGameInfo):
def getSaveGameWidget(self, parent: QWidget | None = None):
2021-09-30 02:34:07 -05:00
return StalkerAnomalySaveGameInfoWidget(parent)
2021-03-02 17:34:19 -06:00
2020-10-16 17:43:30 -05:00
class StalkerAnomalyGame(BasicGame, mobase.IPluginFileMapper):
2020-06-17 16:54:27 -05:00
Name = "STALKER Anomaly"
Author = "Qudix"
2021-09-30 02:34:07 -05:00
Version = "0.5.0"
2020-06-17 16:54:27 -05:00
Description = "Adds support for STALKER Anomaly"
GameName = "STALKER Anomaly"
GameShortName = "stalkeranomaly"
2021-10-05 19:52:00 -05:00
GameNexusName = "stalkeranomaly"
GameNexusId = 3743
2020-06-17 16:54:27 -05:00
GameBinary = "AnomalyLauncher.exe"
GameDataPath = ""
2021-10-01 18:37:12 -05:00
GameDocumentsDirectory = "%GAME_PATH%/appdata"
2021-12-27 00:57:18 -07:00
GameSupportURL = (
r"https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/"
"Game:-S.T.A.L.K.E.R.-Anomaly"
)
2020-10-31 17:46:18 +01:00
2020-06-17 16:54:27 -05:00
GameSaveExtension = "scop"
2021-10-01 18:37:12 -05:00
GameSavesDirectory = "%GAME_DOCUMENTS%/savedgames"
2020-10-16 17:43:30 -05:00
def __init__(self):
BasicGame.__init__(self)
mobase.IPluginFileMapper.__init__(self)
2020-10-31 17:46:18 +01:00
2020-06-17 16:54:27 -05:00
def init(self, organizer: mobase.IOrganizer):
2020-10-16 17:43:30 -05:00
BasicGame.init(self, organizer)
self._register_feature(StalkerAnomalyModDataChecker())
self._register_feature(StalkerAnomalyModDataContent())
self._register_feature(StalkerAnomalySaveGameInfo())
2021-10-01 18:40:05 -05:00
organizer.onAboutToRun(lambda _str: self.aboutToRun(_str))
2020-06-17 16:54:27 -05:00
return True
2021-10-01 18:40:05 -05:00
def aboutToRun(self, _str: str) -> bool:
2021-10-01 18:37:12 -05:00
gamedir = self.gameDirectory()
if gamedir.exists():
# For mappings
gamedir.mkdir("appdata")
# The game will crash if this file exists in the
# virtual tree rather than the game dir
dbg_path = Path(self._gamePath, "gamedata/configs/cache_dbg.ltx")
if not dbg_path.exists():
dbg_path.parent.mkdir(parents=True, exist_ok=True)
with open(dbg_path, "w", encoding="utf-8"):
2021-10-01 18:37:12 -05:00
pass
return True
def executables(self) -> list[mobase.ExecutableInfo]:
2021-09-30 02:34:07 -05:00
info = [
["Anomaly Launcher", "AnomalyLauncher.exe"],
["Anomaly (DX11-AVX)", "bin/AnomalyDX11AVX.exe"],
["Anomaly (DX11)", "bin/AnomalyDX11.exe"],
["Anomaly (DX10-AVX)", "bin/AnomalyDX10AVX.exe"],
["Anomaly (DX10)", "bin/AnomalyDX10.exe"],
["Anomaly (DX9-AVX)", "bin/AnomalyDX9AVX.exe"],
["Anomaly (DX9)", "bin/AnomalyDX9.exe"],
["Anomaly (DX8-AVX)", "bin/AnomalyDX8AVX.exe"],
["Anomaly (DX8)", "bin/AnomalyDX8.exe"],
2020-10-16 17:43:30 -05:00
]
2021-09-30 02:34:07 -05:00
gamedir = self.gameDirectory()
2021-09-30 23:35:32 -05:00
return [
mobase.ExecutableInfo(inf[0], QFileInfo(gamedir, inf[1])) for inf in info
]
2020-10-16 17:43:30 -05:00
def listSaves(self, folder: QDir) -> list[mobase.ISaveGame]:
2021-03-02 17:34:19 -06:00
ext = self._mappings.savegameExtension.get()
return [
StalkerAnomalySaveGame(path)
for path in Path(folder.absolutePath()).glob(f"*.{ext}")
]
def mappings(self) -> list[mobase.Mapping]:
2021-10-01 18:37:12 -05:00
appdata = self.gameDirectory().filePath("appdata")
2020-10-16 17:43:30 -05:00
m = mobase.Mapping()
m.createTarget = True
m.isDirectory = True
2021-10-01 18:37:12 -05:00
m.source = appdata
m.destination = appdata
2020-10-31 17:46:18 +01:00
return [m]