Skip to content

Commit 1a6b157

Browse files
committed
2 parents da570ea + 228682e commit 1a6b157

5 files changed

Lines changed: 112 additions & 4 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ You can rename `modorganizer-basic_games-xxx` to whatever you want (e.g., `basic
8181
| Tony Hawk's Underground 2 | [uwx](https://github.com/uwx) | [game_thug2.py](games/game_thug2.py) | |
8282
| Trackmania United Forever — [STEAM](https://store.steampowered.com/app/7200/Trackmania_United_Forever/) | [uwx](https://github.com/uwx) | [game_tmuf.py](games/game_tmuf.py) | |
8383
| Yu-Gi-Oh! Master Duel — [STEAM](https://store.steampowered.com/app/1449850/) | [The Conceptionist](https://github.com/the-conceptionist) & [uwx](https://github.com/uwx) | [game_masterduel.py](games/game_masterduel.py) | |
84-
| Zeus and Poseidon — [GOG](https://www.gog.com/game/zeus_poseidon) / [STEAM](https://store.steampowered.com/app/566050/Zeus__Poseidon/) | [Holt59](https://github.com/holt59/) | [game_zeusandpoiseidon.py](games/game_zeusandpoiseidon.py) | <ul><li>mod data checker</li></ul> |
84+
| Zeus and Poseidon — [GOG](https://www.gog.com/game/zeus_poseidon) / [STEAM](https://store.steampowered.com/app/566050/Zeus__Poseidon/) | [Holt59](https://github.com/holt59/) | [game_zeusandposeidon.py](games/game_zeusandposeidon.py) | <ul><li>mod data checker</li></ul> |
8585

8686
## How to add a new game?
8787

games/game_darkestdungeon.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ class DarkestDungeonGame(BasicGame):
166166
GameNexusName = "darkestdungeon"
167167
GameNexusId = 804
168168
GameSteamId = 262060
169-
GameGogId = 1719198803
169+
GameGogId = 1450711444
170170
GameBinary = "_windows/win64/Darkest.exe"
171171
GameDataPath = ""
172172
GameDocumentsDirectory = "%DOCUMENTS%/Darkest"

games/game_finalfantasy7rebirth.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def mod_mapping(self) -> Iterable[mobase.Mapping]:
8383

8484

8585
class FinalFantasy7RebirthGame(BasicGame, mobase.IPluginFileMapper):
86-
Name = "Final Fasntasy 7 Rebirth Support Plugin"
86+
Name = "Final Fantasy 7 Rebirth Support Plugin"
8787
Author = "diegofesanto, TheUnlocked"
8888
Version = "0.0.1"
8989

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import os
2+
import xml.etree.ElementTree as ET
3+
from pathlib import Path
4+
5+
from PyQt6.QtCore import QDir, qInfo, qWarning
6+
7+
import mobase
8+
9+
from ..basic_features import BasicModDataChecker, GlobPatterns
10+
from ..basic_game import BasicGame
11+
12+
13+
class KingdomComeDeliverance2Game(BasicGame):
14+
Name = "Kingdom Come: Deliverance 2 Support Plugin"
15+
Author = "TheForgotten69"
16+
Version = "1.0.0"
17+
18+
GameName = "Kingdom Come: Deliverance II"
19+
GameShortName = "kingdomcomedeliverance2"
20+
GameNexusName = "kingdomcomedeliverance2"
21+
GameNexusId = 7286
22+
GameSteamId = [1771300]
23+
GameBinary = "bin/Win64MasterMasterSteamPGO/KingdomCome.exe"
24+
GameDataPath = "Mods"
25+
GameSaveExtension = "whs"
26+
GameDocumentsDirectory = "%GAME_PATH%"
27+
GameSavesDirectory = "%USERPROFILE%/Saved Games/kingdomcome2/saves"
28+
29+
def init(self, organizer: mobase.IOrganizer) -> bool:
30+
super().init(organizer)
31+
self._register_feature(BasicModDataChecker(GlobPatterns(valid=["*"])))
32+
organizer.onAboutToRun(self._write_mod_order)
33+
return True
34+
35+
@staticmethod
36+
def _get_mod_id(mod_path: Path) -> str | None:
37+
"""Return the mod ID for a KCD2 mod.
38+
39+
Checks mod.manifest for <modid> (preferred) or <name>, falling back
40+
to the game mod folder name (the subfolder inside the MO2 mod directory).
41+
"""
42+
for manifest in mod_path.rglob("mod.manifest"):
43+
try:
44+
root = ET.parse(manifest).getroot()
45+
for tag in ("modid", "name"):
46+
elem = root.find(f".//{tag}")
47+
if elem is not None and elem.text and elem.text.strip():
48+
return elem.text.strip()
49+
except ET.ParseError:
50+
qWarning(f"KCD2: failed to parse {manifest}")
51+
# Fall back to the folder that contains mod.manifest
52+
return manifest.parent.name
53+
# No manifest — use first subdirectory name (the game mod folder)
54+
for subdir in mod_path.iterdir():
55+
if subdir.is_dir():
56+
return subdir.name
57+
return None
58+
59+
def _write_mod_order(self, app_path: str, wd: QDir, args: str) -> bool:
60+
if not self.isActive():
61+
return True
62+
63+
modlist = self._organizer.modList()
64+
mods_path = Path(self._organizer.modsPath())
65+
mod_order_path = Path(self._organizer.overwritePath()) / "mod_order.txt"
66+
67+
mod_ids: list[str] = []
68+
for mod_name in modlist.allModsByProfilePriority():
69+
if not (modlist.state(mod_name) & mobase.ModState.ACTIVE):
70+
continue
71+
mod_id = self._get_mod_id(mods_path / mod_name)
72+
if mod_id:
73+
qInfo(f"KCD2: mod '{mod_name}' -> id '{mod_id}'")
74+
mod_ids.append(mod_id)
75+
else:
76+
qWarning(f"KCD2: could not resolve id for mod '{mod_name}', skipping")
77+
78+
if not mod_ids:
79+
mod_order_path.unlink(missing_ok=True)
80+
return True
81+
82+
# MO2 priority 1 = top = highest priority. KCD2 is last-loaded-wins,
83+
# so highest priority must be last in the file.
84+
mod_ids.reverse()
85+
mod_order_path.parent.mkdir(parents=True, exist_ok=True)
86+
mod_order_path.write_text("\n".join(mod_ids))
87+
qInfo(f"KCD2: wrote mod_order.txt with {len(mod_ids)} mods: {mod_ids}")
88+
return True
89+
90+
def iniFiles(self):
91+
return ["custom.cfg", "system.cfg", "user.cfg"]
92+
93+
def initializeProfile(self, directory: QDir, settings: mobase.ProfileSetting):
94+
for iniFile in self.iniFiles():
95+
iniPath = self.documentsDirectory().absoluteFilePath(iniFile)
96+
if not os.path.exists(iniPath):
97+
with open(iniPath, "w") as _:
98+
pass
99+
100+
modsPath = self.dataDirectory().absolutePath()
101+
if not os.path.exists(modsPath):
102+
os.mkdir(modsPath)
103+
104+
super().initializeProfile(directory, settings)

games/game_oblivion_remaster.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,13 @@ def primaryPlugins(self) -> list[str]:
198198
"DLCThievesDen.esp",
199199
"DLCVileLair.esp",
200200
"Knights.esp",
201+
"AltarESPLocal.esp", # Not actually shipped with the game files but present in plugins.txt.
202+
]
203+
204+
def enabledPlugins(self) -> list[str]:
205+
return [
201206
"AltarESPMain.esp",
202207
"AltarDeluxe.esp",
203-
"AltarESPLocal.esp", # Not actually shipped with the game files but present in plugins.txt.
204208
]
205209

206210
def modDataDirectory(self) -> str:

0 commit comments

Comments
 (0)