aboutsummaryrefslogtreecommitdiff
path: root/libs/game_bethesda/src/games/fallout4london/gamefo4london.cpp
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
commit7ee008e150bc5bcf76082d726f719ee0fdfda982 (patch)
tree27fb39be241fdb5ac2734c574de678977d1856d0 /libs/game_bethesda/src/games/fallout4london/gamefo4london.cpp
Fluorine Manager: full Linux port of Mod Organizer 2
Complete native Linux port with FUSE-based virtual filesystem, Proton/umu-run integration, and Flatpak packaging. Key features: - FUSE VFS replacing Windows USVFS (in-process + standalone helper for Flatpak) - Proton/GE-Proton/umu-run launcher with env var forwarding - Flatpak support (sandbox-aware VFS, NXM handler, umu-run) - Wine prefix management UI - Case-insensitive path resolution for Linux filesystems - QSettings-safe INI handling (avoids Bethesda INI corruption) - Portable instance support with auto-generated launcher scripts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'libs/game_bethesda/src/games/fallout4london/gamefo4london.cpp')
-rw-r--r--libs/game_bethesda/src/games/fallout4london/gamefo4london.cpp366
1 files changed, 366 insertions, 0 deletions
diff --git a/libs/game_bethesda/src/games/fallout4london/gamefo4london.cpp b/libs/game_bethesda/src/games/fallout4london/gamefo4london.cpp
new file mode 100644
index 0000000..0fa774a
--- /dev/null
+++ b/libs/game_bethesda/src/games/fallout4london/gamefo4london.cpp
@@ -0,0 +1,366 @@
+#include "gamefo4london.h"
+
+#include "fo4londonbsainvalidation.h"
+#include "fo4londondataarchives.h"
+#include "fo4londonmoddatachecker.h"
+#include "fo4londonmoddatacontent.h"
+#include "fo4londonsavegame.h"
+#include "fo4londonscriptextender.h"
+#include "fo4londonunmanagedmods.h"
+
+#include "versioninfo.h"
+#include <creationgameplugins.h>
+#include <executableinfo.h>
+#include <gamebryolocalsavegames.h>
+#include <gamebryosavegameinfo.h>
+#include <pluginsetting.h>
+
+#include <QCoreApplication>
+#include <QDir>
+#include <QFileInfo>
+#include <QList>
+#include <QObject>
+#include <QString>
+#include <QStringList>
+
+#include <memory>
+
+#include "scopeguard.h"
+
+using namespace MOBase;
+
+const unsigned int GameFallout4London::PROBLEM_TEST_FILE;
+
+GameFallout4London::GameFallout4London() {}
+
+bool GameFallout4London::init(IOrganizer* moInfo)
+{
+ if (!GameGamebryo::init(moInfo)) {
+ return false;
+ }
+
+ auto dataArchives = std::make_shared<Fallout4LondonDataArchives>(this);
+
+ registerFeature(std::make_shared<Fallout4LondonScriptExtender>(this));
+ registerFeature(dataArchives);
+ registerFeature(
+ std::make_shared<GamebryoLocalSavegames>(this, "fo4londoncustom.ini"));
+ registerFeature(std::make_shared<Fallout4LondonModDataChecker>(this));
+ registerFeature(
+ std::make_shared<Fallout4LondonModDataContent>(m_Organizer->gameFeatures()));
+ registerFeature(std::make_shared<GamebryoSaveGameInfo>(this));
+ registerFeature(std::make_shared<CreationGamePlugins>(moInfo));
+ registerFeature(std::make_shared<Fallout4LondonUnmangedMods>(this));
+ registerFeature(
+ std::make_shared<Fallout4LondonBSAInvalidation>(dataArchives.get(), this));
+
+ return true;
+}
+
+QString GameFallout4London::gameName() const
+{
+ return "Fallout 4 London";
+}
+
+void GameFallout4London::detectGame()
+{
+ m_GamePath = identifyGamePath();
+ m_MyGamesPath = determineMyGamesPath("Fallout4");
+}
+
+QString GameFallout4London::identifyGamePath() const
+{
+#ifdef _WIN32
+ // TODO: Add GOG support
+ QString path = "Software\\Bethesda Softworks\\Fallout4";
+ return findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(),
+ L"Installed Path");
+#else
+ return GameGamebryo::identifyGamePath();
+#endif
+}
+
+QList<ExecutableInfo> GameFallout4London::executables() const
+{
+ return QList<ExecutableInfo>()
+ << ExecutableInfo("F4SE",
+ findInGameFolder(m_Organizer->gameFeatures()
+ ->gameFeature<MOBase::ScriptExtender>()
+ ->loaderName()))
+ << ExecutableInfo("Fallout 4 London", findInGameFolder(binaryName()))
+ << ExecutableInfo("Fallout Launcher", findInGameFolder(getLauncherName()))
+ << ExecutableInfo("Creation Kit", findInGameFolder("CreationKit.exe"))
+ .withSteamAppId("1946160")
+ << ExecutableInfo("LOOT", QFileInfo(getLootPath()))
+ .withArgument("--game=\"Fallout4\"");
+}
+
+QList<ExecutableForcedLoadSetting> GameFallout4London::executableForcedLoads() const
+{
+ return QList<ExecutableForcedLoadSetting>();
+}
+
+QString GameFallout4London::name() const
+{
+ return "Fallout 4 London Support Plugin";
+}
+
+QString GameFallout4London::localizedName() const
+{
+ return tr("Fallout 4 London Support Plugin");
+}
+
+QString GameFallout4London::author() const
+{
+ return "MO2 Team";
+}
+
+QString GameFallout4London::description() const
+{
+ return tr("Adds support for the game Fallout 4 London.");
+}
+
+MOBase::VersionInfo GameFallout4London::version() const
+{
+ return VersionInfo(0, 0, 1, VersionInfo::RELEASE_PREALPHA);
+}
+
+QList<PluginSetting> GameFallout4London::settings() const
+{
+ return QList<PluginSetting>();
+}
+
+MappingType GameFallout4London::mappings() const
+{
+ MappingType result;
+ if (testFilePlugins().isEmpty()) {
+ for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) {
+ result.push_back({m_Organizer->profilePath() + "/" + profileFile,
+ localAppFolder() + "/Fallout4/" + profileFile, false});
+ }
+ }
+ return result;
+}
+
+void GameFallout4London::initializeProfile(const QDir& path,
+ ProfileSettings settings) const
+{
+ if (settings.testFlag(IPluginGame::MODS)) {
+ copyToProfile(localAppFolder() + "/Fallout4", path, "plugins.txt");
+ }
+
+ if (settings.testFlag(IPluginGame::CONFIGURATION)) {
+ if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) ||
+ !QFileInfo(myGamesPath() + "/fallout4.ini").exists()) {
+ copyToProfile(gameDirectory().absolutePath(), path, "fallout4_default.ini",
+ "fallout4.ini");
+ } else {
+ copyToProfile(myGamesPath(), path, "fallout4.ini");
+ }
+
+ copyToProfile(myGamesPath(), path, "fallout4prefs.ini");
+ copyToProfile(myGamesPath(), path, "fallout4custom.ini");
+ }
+}
+
+QString GameFallout4London::savegameExtension() const
+{
+ return "fos";
+}
+
+QString GameFallout4London::savegameSEExtension() const
+{
+ return "f4se";
+}
+
+std::shared_ptr<const GamebryoSaveGame>
+GameFallout4London::makeSaveGame(QString filePath) const
+{
+ return std::make_shared<const Fallout4LondonSaveGame>(filePath, this);
+}
+
+QString GameFallout4London::steamAPPId() const
+{
+ return "377160";
+}
+
+QStringList GameFallout4London::testFilePlugins() const
+{
+ QStringList plugins;
+ if (m_Organizer != nullptr && m_Organizer->profile() != nullptr) {
+ QString customIni(
+ m_Organizer->profile()->absoluteIniFilePath("Fallout4Custom.ini"));
+ if (QFile(customIni).exists()) {
+ for (int i = 1; i <= 10; ++i) {
+ QString setting("sTestFile");
+ setting += std::to_string(i);
+ QString plugin = GameGamebryo::readIniValue(customIni, "General", setting, "");
+ if (!plugin.isEmpty() && !plugins.contains(plugin, Qt::CaseInsensitive)) {
+ plugins.append(plugin);
+ }
+ }
+ }
+ }
+ return plugins;
+}
+
+QStringList GameFallout4London::primaryPlugins() const
+{
+ QStringList plugins = {"fallout4.esm", "dlcrobot.esm",
+ "dlcworkshop01.esm", "dlccoast.esm",
+ "dlcworkshop02.esm", "dlcworkshop03.esm",
+ "dlcnukaworld.esm", "dlcultrahighresolution.esm"};
+
+ auto testPlugins = testFilePlugins();
+ if (loadOrderMechanism() == LoadOrderMechanism::None) {
+ plugins << testPlugins;
+ } else {
+ plugins << CCPlugins();
+ }
+
+ return plugins;
+}
+
+QStringList GameFallout4London::enabledPlugins() const
+{
+ return {"bakaframework.esm", "londonworldspace.esm", "londonworldspace-dlcblock.esp"};
+}
+
+QStringList GameFallout4London::gameVariants() const
+{
+ return {"Regular"};
+}
+
+QString GameFallout4London::gameShortName() const
+{
+ return "Fallout4London";
+}
+
+QStringList GameFallout4London::validShortNames() const
+{
+ return {"Fallout4"};
+}
+
+QString GameFallout4London::gameNexusName() const
+{
+ return "fallout4london";
+}
+
+QString GameFallout4London::binaryName() const
+{
+ return "Fallout4.exe";
+}
+
+QString GameFallout4London::getLauncherName() const
+{
+ return "Fallout4Launcher.exe";
+}
+
+QStringList GameFallout4London::iniFiles() const
+{
+ return {"fallout4.ini", "fallout4prefs.ini", "fallout4custom.ini"};
+}
+
+QStringList GameFallout4London::DLCPlugins() const
+{
+ return {"dlcrobot.esm",
+ "dlcworkshop01.esm",
+ "dlccoast.esm",
+ "dlcworkshop02.esm",
+ "dlcworkshop03.esm",
+ "dlcnukaworld.esm",
+ "dlcultrahighresolution.esm"};
+}
+
+QStringList GameFallout4London::CCPlugins() const
+{
+ QStringList plugins = {};
+ QFile file(gameDirectory().absoluteFilePath("Fallout4.ccc"));
+ if (file.open(QIODevice::ReadOnly)) {
+ ON_BLOCK_EXIT([&file]() {
+ file.close();
+ });
+
+ if (file.size() == 0) {
+ return plugins;
+ }
+ while (!file.atEnd()) {
+ QByteArray line = file.readLine().trimmed();
+ QString modName;
+ if ((line.size() > 0) && (line.at(0) != '#')) {
+ modName = QString::fromUtf8(line.constData()).toLower();
+ }
+
+ if (modName.size() > 0) {
+ if (!plugins.contains(modName, Qt::CaseInsensitive)) {
+ plugins.append(modName);
+ }
+ }
+ }
+ }
+ return plugins;
+}
+
+IPluginGame::SortMechanism GameFallout4London::sortMechanism() const
+{
+ if (!testFilePresent())
+ return IPluginGame::SortMechanism::LOOT;
+ return IPluginGame::SortMechanism::NONE;
+}
+
+IPluginGame::LoadOrderMechanism GameFallout4London::loadOrderMechanism() const
+{
+ if (!testFilePresent())
+ return IPluginGame::LoadOrderMechanism::PluginsTxt;
+ return IPluginGame::LoadOrderMechanism::None;
+}
+
+int GameFallout4London::nexusModOrganizerID() const
+{
+ return 28715;
+}
+
+int GameFallout4London::nexusGameID() const
+{
+ return 1151;
+}
+
+// Start Diagnose
+std::vector<unsigned int> GameFallout4London::activeProblems() const
+{
+ std::vector<unsigned int> result;
+ if (m_Organizer->managedGame() == this) {
+ if (testFilePresent())
+ result.push_back(PROBLEM_TEST_FILE);
+ }
+ return result;
+}
+
+bool GameFallout4London::testFilePresent() const
+{
+ if (!testFilePlugins().isEmpty())
+ return true;
+ return false;
+}
+
+QString GameFallout4London::shortDescription(unsigned int key) const
+{
+ switch (key) {
+ case PROBLEM_TEST_FILE:
+ return tr("sTestFile entries are present");
+ }
+ return QString();
+}
+
+QString GameFallout4London::fullDescription(unsigned int key) const
+{
+ switch (key) {
+ case PROBLEM_TEST_FILE: {
+ return tr("<p>You have sTestFile settings in your "
+ "Fallout4Custom.ini. These must be removed or "
+ "the game will not read the plugins.txt file. "
+ "Management is disabled.</p>");
+ }
+ }
+ return QString();
+}