Skip to content

Commit 109daf6

Browse files
committed
updated some comments and redudencies
1 parent d78cf05 commit 109daf6

4 files changed

Lines changed: 77 additions & 103 deletions

File tree

games/game_stalker2heartofchornobyl.py

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ class Problems(IntEnum):
1313
"""
1414
Enums for IPluginDiagnose.
1515
"""
16-
# PAK files placed in incorrect locations
1716
MISPLACED_PAK_FILES = auto()
18-
# Missing mod directory structure
1917
MISSING_MOD_DIRECTORIES = auto()
2018

2119

@@ -24,7 +22,6 @@ class S2HoCGame(BasicGame, mobase.IPluginFileMapper, mobase.IPluginDiagnose):
2422
Author = "MkHaters"
2523
Version = "1.1.0"
2624

27-
# Game details for MO2, using paths common for Unreal Engine-based games.
2825
GameName = "Stalker 2: Heart of Chornobyl"
2926
GameShortName = "stalker2heartofchornobyl"
3027
GameNexusName = "stalker2heartofchornobyl"
@@ -35,27 +32,32 @@ class S2HoCGame(BasicGame, mobase.IPluginFileMapper, mobase.IPluginDiagnose):
3532
GameSteamId = 1643320
3633
GameGogId = 1529799785
3734
GameBinary = "Stalker2.exe"
38-
GameDataPath = "%GAME_PATH%/Stalker2"
35+
GameDataPath = "Stalker2"
3936
GameIniFiles = [
4037
"%GAME_DOCUMENTS%/Saved/Config/Windows/Game.ini",
4138
"%GAME_DOCUMENTS%/Saved/Config/Windows/GameUserSettings.ini",
4239
"%GAME_DOCUMENTS%/Saved/Config/Windows/Engine.ini"
4340
]
4441

4542
_main_window: QMainWindow
46-
_paks_tab: QWidget # Will be S2HoCPaksTabWidget when imported
43+
_paks_tab: QWidget
4744

4845
def __init__(self):
49-
# Initialize parent classes.
5046
BasicGame.__init__(self)
5147
mobase.IPluginFileMapper.__init__(self)
5248
mobase.IPluginDiagnose.__init__(self)
5349

5450
def resolve_path(self, path: str) -> str:
55-
# Replace MO2 variables with actual paths
5651
path = path.replace("%USERPROFILE%", os.environ.get("USERPROFILE", ""))
57-
path = path.replace("%GAME_DOCUMENTS%", self.GameDocumentsDirectory)
58-
path = path.replace("%GAME_PATH%", self.GameDataPath)
52+
53+
if "%GAME_DOCUMENTS%" in path:
54+
game_docs = self.GameDocumentsDirectory.replace("%USERPROFILE%", os.environ.get("USERPROFILE", ""))
55+
path = path.replace("%GAME_DOCUMENTS%", game_docs)
56+
57+
if "%GAME_PATH%" in path:
58+
game_path = self._gamePath if hasattr(self, '_gamePath') else ""
59+
path = path.replace("%GAME_PATH%", game_path)
60+
5961
return path
6062

6163
def init(self, organizer: mobase.IOrganizer) -> bool:
@@ -65,25 +67,21 @@ def init(self, organizer: mobase.IOrganizer) -> bool:
6567
BasicLocalSavegames(QDir(self.resolve_path(self.GameSavesDirectory)))
6668
)
6769

68-
# Create the directory more reliably
6970
if (
7071
self._organizer.managedGame()
7172
and self._organizer.managedGame().gameName() == self.gameName()
7273
):
73-
# Get the absolute path as a string
7474
mod_path = self.paksModsDirectory().absolutePath()
7575
try:
76-
# Create the directory with parents if needed
7776
os.makedirs(mod_path, exist_ok=True)
78-
# Verify the directory was actually created
7977
if not os.path.exists(mod_path):
80-
print(f"Warning: Failed to create directory: {mod_path}")
78+
self._organizer.log(mobase.LogLevel.WARNING, f"Failed to create directory: {mod_path}")
79+
except OSError as e:
80+
self._organizer.log(mobase.LogLevel.ERROR, f"OS error creating mod directory: {e}")
8181
except Exception as e:
82-
print(f"Error creating mod directory: {e}")
82+
self._organizer.log(mobase.LogLevel.ERROR, f"Unexpected error creating mod directory: {e}")
8383

84-
# Initialize PAK tab when UI is ready
8584
organizer.onUserInterfaceInitialized(self.init_tab)
86-
8785
return True
8886

8987
def init_tab(self, main_window: QMainWindow):
@@ -97,54 +95,59 @@ def init_tab(self, main_window: QMainWindow):
9795
self._main_window = main_window
9896
tab_widget: QTabWidget = main_window.findChild(QTabWidget, "tabWidget")
9997
if not tab_widget:
100-
print("No main tab widget found!")
98+
self._organizer.log(mobase.LogLevel.WARNING, "No main tab widget found!")
10199
return
102100

103-
# Import here to avoid circular imports
104101
from .stalker2heartofchornobyl.paks import S2HoCPaksTabWidget
105102
self._paks_tab = S2HoCPaksTabWidget(main_window, self._organizer)
106103

107-
# Insert after the last tab (like Oblivion Remastered)
108104
tab_widget.addTab(self._paks_tab, "PAK Files")
109-
print("PAK Files tab added!")
105+
self._organizer.log(mobase.LogLevel.INFO, "PAK Files tab added!")
106+
except ImportError as e:
107+
self._organizer.log(mobase.LogLevel.ERROR, f"Failed to import PAK tab widget: {e}")
110108
except Exception as e:
111-
print(f"Error initializing PAK tab: {e}")
109+
self._organizer.log(mobase.LogLevel.ERROR, f"Error initializing PAK tab: {e}")
112110
import traceback
113111
traceback.print_exc()
114112

115113
def mappings(self) -> List[mobase.Mapping]:
116-
return [
117-
mobase.Mapping("*.pak", "Content/Paks/~mods/", False),
118-
mobase.Mapping("*.utoc", "Content/Paks/~mods/", False),
119-
mobase.Mapping("*.ucas", "Content/Paks/~mods/", False),
120-
mobase.Mapping("Paks/*.pak", "Content/Paks/~mods/", False),
121-
mobase.Mapping("Paks/*.utoc", "Content/Paks/~mods/", False),
122-
mobase.Mapping("Paks/*.ucas", "Content/Paks/~mods/", False),
123-
mobase.Mapping("~mods/*.pak", "Content/Paks/~mods/", False),
124-
mobase.Mapping("~mods/*.utoc", "Content/Paks/~mods/", False),
125-
mobase.Mapping("~mods/*.ucas", "Content/Paks/~mods/", False),
126-
mobase.Mapping("Content/Paks/~mods/*.pak", "Content/Paks/~mods/", False),
127-
mobase.Mapping("Content/Paks/~mods/*.utoc", "Content/Paks/~mods/", False),
128-
mobase.Mapping("Content/Paks/~mods/*.ucas", "Content/Paks/~mods/", False),
129-
]
114+
pak_extensions = ["*.pak", "*.utoc", "*.ucas"]
115+
target_dir = "Content/Paks/~mods/"
116+
117+
mappings = []
118+
119+
for ext in pak_extensions:
120+
mappings.append(mobase.Mapping(ext, target_dir, False))
121+
122+
source_dirs = ["Paks/", "~mods/", "Content/Paks/~mods/"]
123+
for source_dir in source_dirs:
124+
for ext in pak_extensions:
125+
mappings.append(mobase.Mapping(f"{source_dir}{ext}", target_dir, False))
126+
127+
return mappings
130128

131129
def gameDirectory(self) -> QDir:
132130
return QDir(self._gamePath)
133131

134132
def paksDirectory(self) -> QDir:
135-
return QDir(self.gameDirectory().absolutePath() + "/Stalker2/Content/Paks")
133+
path = os.path.join(self.gameDirectory().absolutePath(), self.GameDataPath, "Content", "Paks")
134+
return QDir(path)
136135

137136
def paksModsDirectory(self) -> QDir:
138-
# Use os.path.join for more reliable path construction
139-
path = os.path.join(self.paksDirectory().absolutePath(), "~mods")
140-
return QDir(path)
137+
try:
138+
path = os.path.join(self.paksDirectory().absolutePath(), "~mods")
139+
return QDir(path)
140+
except Exception as e:
141+
fallback = os.path.join(self.gameDirectory().absolutePath(), self.GameDataPath, "Content", "Paks", "~mods")
142+
return QDir(fallback)
141143

142144
def logicModsDirectory(self) -> QDir:
143-
# Update path to place LogicMods under Paks
144-
return QDir(self.gameDirectory().absolutePath() + "/Stalker2/Content/Paks/LogicMods")
145+
path = os.path.join(self.gameDirectory().absolutePath(), self.GameDataPath, "Content", "Paks", "LogicMods")
146+
return QDir(path)
145147

146148
def binariesDirectory(self) -> QDir:
147-
return QDir(self.gameDirectory().absolutePath() + "/Stalker2/Binaries/Win64")
149+
path = os.path.join(self.gameDirectory().absolutePath(), self.GameDataPath, "Binaries", "Win64")
150+
return QDir(path)
148151

149152
def getModMappings(self) -> dict[str, list[str]]:
150153
return {
@@ -155,18 +158,15 @@ def activeProblems(self) -> list[int]:
155158
problems = set()
156159
if self._organizer.managedGame() == self:
157160

158-
# More reliable directory check using os.path
159161
mod_path = self.paksModsDirectory().absolutePath()
160162
if not os.path.isdir(mod_path):
161163
problems.add(Problems.MISSING_MOD_DIRECTORIES)
162-
print(f"Missing mod directory: {mod_path}")
164+
self._organizer.log(mobase.LogLevel.DEBUG, f"Missing mod directory: {mod_path}")
163165

164-
# Check for misplaced PAK files
165166
for mod in self._organizer.modList().allMods():
166167
mod_info = self._organizer.modList().getMod(mod)
167168
filetree = mod_info.fileTree()
168169

169-
# Check for PAK files at the root level (remove LogicMods paths)
170170
for entry in filetree:
171171
if entry.name().endswith(('.pak', '.utoc', '.ucas')) and not any(
172172
entry.path().startswith(p) for p in ['Content/Paks/~mods', 'Paks', '~mods']
@@ -216,21 +216,22 @@ def shortDescription(self, key: int) -> str:
216216
def startGuidedFix(self, key: int) -> None:
217217
match key:
218218
case Problems.MISSING_MOD_DIRECTORIES:
219-
# Create only the ~mods directory
220-
os.makedirs(self.paksModsDirectory().absolutePath(), exist_ok=True)
219+
try:
220+
os.makedirs(self.paksModsDirectory().absolutePath(), exist_ok=True)
221+
self._organizer.log(mobase.LogLevel.INFO, "Created missing mod directories")
222+
except Exception as e:
223+
self._organizer.log(mobase.LogLevel.ERROR, f"Failed to create mod directories: {e}")
221224
case _:
222225
pass
223226

224227

225228
class S2HoCModDataChecker(BasicModDataChecker):
226229
def __init__(self, patterns: GlobPatterns = GlobPatterns()):
227-
# Define valid mod directories and the file movement rules.
228230
move_patterns = {
229231
"*.pak": "Content/Paks/~mods/",
230232
"*.utoc": "Content/Paks/~mods/",
231233
"*.ucas": "Content/Paks/~mods/"
232234
}
233-
# Define valid mod roots - remove LogicMods
234235
valid_roots = ["Content", "Paks", "~mods"]
235236
base_patterns = GlobPatterns(valid=valid_roots, move=move_patterns)
236237
merged_patterns = base_patterns.merge(patterns)

games/stalker2heartofchornobyl/paks/model.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,16 @@ def _init_mod_states(self):
3939
profile = QDir(self._organizer.profilePath())
4040
paks_txt = QFileInfo(profile.absoluteFilePath("stalker2_paks.txt"))
4141
if paks_txt.exists():
42-
with open(paks_txt.absoluteFilePath(), "r") as paks_file:
43-
index = 0
44-
for line in paks_file:
45-
self.paks[index] = (line.strip(), "", "", "")
46-
index += 1
42+
try:
43+
with open(paks_txt.absoluteFilePath(), "r", encoding="utf-8") as paks_file:
44+
index = 0
45+
for line in paks_file:
46+
stripped_line = line.strip()
47+
if stripped_line:
48+
self.paks[index] = (stripped_line, "", "", "")
49+
index += 1
50+
except (IOError, OSError) as e:
51+
pass
4752

4853
def set_paks(self, paks: dict[int, _PakInfo]):
4954
self.layoutAboutToBeChanged.emit()
@@ -66,7 +71,8 @@ def flags(self, index: QModelIndex) -> Qt.ItemFlag:
6671
return (
6772
super().flags(index)
6873
| Qt.ItemFlag.ItemIsDragEnabled
69-
| Qt.ItemFlag.ItemIsDropEnabled & Qt.ItemFlag.ItemIsEditable
74+
| Qt.ItemFlag.ItemIsDropEnabled
75+
| Qt.ItemFlag.ItemIsEditable
7076
)
7177

7278
def columnCount(self, parent: QModelIndex = QModelIndex()) -> int:
@@ -198,6 +204,7 @@ def dropMimeData(
198204
before_paks_p: list[_PakInfo] = []
199205
moved_paks_p: list[_PakInfo] = []
200206
after_paks_p: list[_PakInfo] = []
207+
201208
for row, paks in sorted(self.paks.items()):
202209
if row < new_priority:
203210
if row in source_rows:
@@ -250,4 +257,4 @@ def dropMimeData(
250257
index -= 1
251258

252259
self.set_paks(new_paks)
253-
return False
260+
return True

games/stalker2heartofchornobyl/paks/view.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ def __init__(self, parent: QWidget | None):
2222
self.setRootIsDecorated(False)
2323

2424
def dropEvent(self, e: QDropEvent | None):
25-
super().dropEvent(e)
26-
self.clearSelection()
27-
self.data_dropped.emit()
25+
if e is not None:
26+
super().dropEvent(e)
27+
self.clearSelection()
28+
self.data_dropped.emit()
2829

2930
def dataChanged(
3031
self, topLeft: QModelIndex, bottomRight: QModelIndex, roles: Iterable[int] = ()

0 commit comments

Comments
 (0)