Home

Awesome

Mod Organizer 2 - Simple Games Plugin

Mod Organizer 2 meta-plugin to make creating game plugins easier and faster.

Why?

In order to create a MO2 game plugin, one must implement the IPluginGame interface. This interface was initially designed for Bethesda games such as the Elder Scrolls or Fallout series and thus contains a lot of things that are irrelevant for most games.

The goal of this meta-plugin is to allow creating game plugins for "basic" games by providing a very simple python class.

How to install?

Download the archive for your MO2 version and extract it directly into your MO2 plugins folder.

Important: Extract the folder in your plugins folder, not the individual files. Your plugins folder should look like this:

dlls/
plugins/
  data/
  basic_games/
    games/
      __init__.py
      ...
    __init__.py
    basic_game.py
    ...
  bsa_extractor.dll
  ...
ModOrganizer.exe

You can rename modorganizer-basic_games-xxx to whatever you want (e.g., basic_games).

Supported games

GameAuthorFileExtras
The Binding of Isaac: Rebirth — STEAMEzioTheDeadPoetgame_thebindingofisaacrebirth.py<ul><li>profile specific ini file</li></ul>
Control — STEAM / GOG / EGSZashgame_control.py
Darkest Dungeon — GOG / STEAMerri120game_darkestdungeon.py<ul><li>save slot parsing</li><li>mod data checker</li></ul>
Dark Messiah of Might & Magic — STEAMHolt59game_darkmessiahofmightandmagic.py<ul><li>save game preview</li></ul>
Dark Souls — STEAMHolt59game_darksouls.py
Divinity: Original Sin (Classic) — STEAMLostDragonistgame_divinityoriginalsin.py<ul><li>save game preview</li></ul>
Divinity: Original Sin (Enhanced Edition) — STEAMLostDragonistgame_divinityoriginalsinee.py<ul><li>save game preview</li><li>mod data checker</li></ul>
Dragon's Dogma: Dark Arisen — GOG / STEAMEzioTheDeadPoetgame_dragonsdogmadarkarisen.py
Dungeon Siege II — GOG / STEAMHolt59game_dungeonsiege2.py<ul><li>mod data checker</li></ul>
Kingdom Come: Deliverance — GOG / STEAM / EpicSilencer711game_kingdomcomedeliverance.py<ul><li>profile specific cfg files</li></ul>
METAL GEAR SOLID 2: Sons of Liberty — STEAMAkiraJkrgame_metalgearsolid2mc.py
METAL GEAR SOLID 3: Snake Eater — STEAMAkiraJkrgame_metalgearsolid3mc.py
Mirror's Edge — GOG / STEAMEzioTheDeadPoetgame_mirrorsedge.py
Mount & Blade II: Bannerlord — GOG / STEAMHolt59game_mountandblade2.py<ul><li>mod data checker</li></ul>
Need for Speed: High Stakesuwxgame_nfshs.py
No Man's Sky - GOG / SteamEzioTheDeadPoetgame_nomanssky.py
S.T.A.L.K.E.R. Anomaly — MODQudixgame_stalkeranomaly.py<ul><li>mod data checker</li></ul>
Stardew Valley — GOG / STEAMSyer10, Holt59game_stardewvalley.py<ul><li>mod data checker</li></ul>
STAR WARS™ Empire at War: Gold Pack - GOG / STEAMerri120<ul><li>Empire at War: game_starwars-empire-at-war.py</li><li>Force of Corruption: game_starwars-empire-at-war-foc.py</li></ul>
Subnautica — STEAM / Epicdekart811, Zashgame_subnautica.py<ul><li>mod data checker</li><li>save game preview</li></ul>
Subnautica: Below Zero — STEAMdekart811, Zashgame_subnautica-below-zero.py<ul><li>mod data checker</li><li>save game preview</li></ul>
Train Simulator Classic — STEAMRyan Younggame_trainsimulator.py
Valheim — STEAMZashgame_valheim.py<ul><li>mod data checker</li><li>overwrite config sync</li><li>save game support (no preview)</li></ul>
Test Drive Unlimiteduwxgame_tdu.py
Test Drive Unlimited 2 — STEAMuwxgame_tdu2.py
The Witcher: Enhanced Edition - GOG / STEAMerri120game_witcher1.py<ul><li>save game parsing (no preview)</li></ul>
The Witcher 3: Wild Hunt — GOG / STEAMHolt59game_witcher3.py<ul><li>save game preview</li></ul>
Tony Hawk's Pro Skater 3uwxgame_thps3.py
Tony Hawk's Pro Skater 4uwxgame_thps4.py
Tony Hawk's Undergrounduwxgame_thug.py
Tony Hawk's Underground 2uwxgame_thug2.py
Trackmania United Forever — STEAMuwxgame_tmuf.py
Yu-Gi-Oh! Master Duel — STEAMThe Conceptionist & uwxgame_masterduel.py
Zeus and Poseidon — GOG / STEAMHolt59game_zeusandpoiseidon.py<ul><li>mod data checker</li></ul>

How to add a new game?

You can create a plugin by providing a python class in the games folder.

Note: If your game plugin does not load properly, you should set the log level to debug and look at the mo_interface.log file.

You need to create a class that inherits BasicGame and put it in a game_XX.py in games. Below is an example for The Witcher 3 (see also games/game_witcher3.py):

from PyQt6.QtCore import QDir
from ..basic_game import BasicGame


class Witcher3Game(BasicGame):

    Name = "Witcher 3 Support Plugin"
    Author = "Holt59"
    Version = "1.0.0a"

    GameName = "The Witcher 3"
    GameShortName = "witcher3"
    GameBinary = "bin/x64/witcher3.exe"
    GameDataPath = "Mods"
    GameSaveExtension = "sav"
    GameSteamId = 292030

    def savesDirectory(self):
        return QDir(self.documentsDirectory().absoluteFilePath("gamesaves"))

BasicGame inherits IPluginGame so you can override methods if you need to. Each attribute you provide corresponds to a method (e.g., Version corresponds to the version method, see the table below). If you override the method, you do not have to provide the attribute:

from PyQt6.QtCore import QDir
from ..basic_game import BasicGame

import mobase


class Witcher3Game(BasicGame):

    Name = "Witcher 3 Support Plugin"
    Author = "Holt59"

    GameName = "The Witcher 3"
    GameShortName = "witcher3"
    GameBinary = "bin/x64/witcher3.exe"
    GameDataPath = "Mods"
    GameSaveExtension = "sav"
    GameSteamId = 292030

    def version(self):
        # Don't forget to import mobase!
        return mobase.VersionInfo(1, 0, 0, mobase.ReleaseType.final)

    def savesDirectory(self):
        return QDir(self.documentsDirectory().absoluteFilePath("gamesaves"))

List of valid keys

NameDescriptionIPluginGame methodPython
NameName of the pluginnamestr
AuthorAuthor of the pluginauthorstr
VersionVersion of the pluginversionstr or mobase.VersionInfo
DescriptionDescription (Optional)descriptionstr
GameNameName of the game, as displayed by MO2gameNamestr
GameShortNameShort name of the gamegameShortNamestr
GameNexusNameNexus name of the game (Optional, default to GameShortName)gameNexusNamestr
GameValidShortNamesOther valid short names (Optional)validShortNamesList[str] or comma-separated list of values
GameNexusIdNexus ID of the game (Optional)nexusGameIDstr or int
GameBinaryName of the game executable, relative to the game pathbinaryNamestr
GameLauncherName of the game launcher, relative to the game path (Optional)getLauncherNamestr
GameDataPathName of the folder containing mods, relative to game folderdataDirectory
GameDocumentsDirectoryDocuments directory (Optional)documentsDirectorystr or QDir
GameIniFilesConfig files in documents, for profile specific config (Optional)iniFilesstr or List[str]
GameSavesDirectoryDirectory containing saves (Optional, default to GameDocumentsDirectory)savesDirectorystr or QDir
GameSaveExtensionSave file extension (Optional) savegameExtensionstr
GameSteamIdSteam ID of the game (Optional)steamAPPIdList[str] or str or int
GameGogIdGOG ID of the game (Optional)gogAPPIdList[str] or str or int
GameOriginManifestIdsOrigin Manifest ID of the game (Optional)originManifestIdsList[str] or str
GameOriginWatcherExecutablesExecutables to watch for Origin DRM (Optional)originWatcherExecutablesList[str] or str
GameEpicIdEpic ID (AppName) of the game (Optional)epicAPPIdList[str] or str
GameEaDesktopIdEA Desktop ID of the game (Optional)eaDesktopContentIdList[str] or str or int

You can use the following variables for str:

Extra features

The meta-plugin provides some useful extra feature:

  1. Automatic Steam, GOG, Origin, Epic Games and EA Desktop detection: If you provide Steam, GOG, Origin or Epic IDs for the game (via GameSteamId, GameGogId, GameOriginManifestIds, GameEpicId or GameEaDesktopId), the game will be listed in the list of available games when creating a new MO2 instance (if the game is installed via Steam, GOG, Origin, Epic Games / Legendary or EA Desktop).
  2. Basic save game preview / metadata (Python): If you can easily obtain a picture (file) and/or metadata (like from json) for any saves, you can provide basic save-game preview by using the BasicGameSaveGameInfo. See games/game_witcher3.py and games/game_bladeandsorcery.py for more details.
  3. Basic local save games (Python): profile specific save games, as in games/game_valheim.py.
  4. Basic mod data checker (Python): Check and fix different mod archive layouts for an automatic installation with the proper file structure, using simple (glob) patterns via BasicModDataChecker. See games/game_valheim.py and game_subnautica.py for an example.

Game IDs can be found here:

Contribute

We recommend using a dedicated Python environment to write a new basic game plugins.

  1. Install the required version of Python --- Currently Python 3.11 (MO2 2.5).
  2. Remove the repository at ${MO2_INSTALL}/plugins/basic_games.
  3. Clone this repository at the location of the old plugin ( ${MO2_INSTALL}/plugins/basic_games).
  4. Place yourself inside the cloned folder and:
# create a virtual environment (recommended)
py -3.11 -m venv .\venv
.\venv\scripts\Activate.ps1

# "install" poetry and the development package
pip install poetry
poetry install