From 7ee008e150bc5bcf76082d726f719ee0fdfda982 Mon Sep 17 00:00:00 2001 From: SulfurNitride Date: Wed, 11 Feb 2026 02:37:39 -0600 Subject: 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 --- .../src/games/fallout76/gamefallout76.cpp | 227 +++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 libs/game_bethesda/src/games/fallout76/gamefallout76.cpp (limited to 'libs/game_bethesda/src/games/fallout76/gamefallout76.cpp') diff --git a/libs/game_bethesda/src/games/fallout76/gamefallout76.cpp b/libs/game_bethesda/src/games/fallout76/gamefallout76.cpp new file mode 100644 index 0000000..bfeb507 --- /dev/null +++ b/libs/game_bethesda/src/games/fallout76/gamefallout76.cpp @@ -0,0 +1,227 @@ +#include "gamefallout76.h" + +#include "fallout76dataarchives.h" +#include "fallout76moddatachecker.h" +#include "fallout76moddatacontent.h" +#include "fallout76unmanagedmods.h" + +#include "versioninfo.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "scopeguard.h" + +using namespace MOBase; + +GameFallout76::GameFallout76() {} + +bool GameFallout76::init(IOrganizer* moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + + registerFeature(std::make_shared(this)); + registerFeature(std::make_shared(this)); + registerFeature( + std::make_shared(m_Organizer->gameFeatures())); + registerFeature(std::make_shared(moInfo)); + registerFeature(std::make_shared(this)); + + return true; +} + +QString GameFallout76::gameName() const +{ + return "Fallout 76"; +} + +void GameFallout76::detectGame() +{ + m_GamePath = identifyGamePath(); + m_MyGamesPath = determineMyGamesPath(gameName()); +} + +QList GameFallout76::executables() const +{ + return QList() + << ExecutableInfo("Fallout 76", findInGameFolder(binaryName())); +} + +QList GameFallout76::executableForcedLoads() const +{ + return {}; +} + +QString GameFallout76::name() const +{ + return "Fallout 76 Support Plugin"; +} + +QString GameFallout76::author() const +{ + return "Mod Organizer Team; EntranceJew"; +} + +QString GameFallout76::description() const +{ + return tr("Adds support for the game Fallout 76.\n" + "Splash by %1") + .arg("nekoyoubi"); +} + +MOBase::VersionInfo GameFallout76::version() const +{ + return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); +} + +QList GameFallout76::settings() const +{ + return QList(); +} + +void GameFallout76::initializeProfile(const QDir& path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/Fallout76", path, "plugins.txt"); + copyToProfile(localAppFolder() + "/Fallout76", path, "loadorder.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || + !QFileInfo(myGamesPath() + "/Fallout76.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "Fallout76_default.ini", + "Fallout76.ini"); + } else { + copyToProfile(myGamesPath(), path, "Fallout76.ini"); + } + + copyToProfile(myGamesPath(), path, "Fallout76Prefs.ini"); + copyToProfile(myGamesPath(), path, "Fallout76Custom.ini"); + } +} + +QString GameFallout76::savegameExtension() const +{ + return ""; +} + +QString GameFallout76::savegameSEExtension() const +{ + return ""; +} + +std::vector> +GameFallout76::listSaves(QDir folder) const +{ + return {}; +} + +QString GameFallout76::identifyGamePath() const +{ + return parseSteamLocation(steamAPPId(), gameShortName()); +} + +std::shared_ptr GameFallout76::makeSaveGame(QString) const +{ + return nullptr; +} + +QString GameFallout76::steamAPPId() const +{ + return "1151340"; +} + +QStringList GameFallout76::primaryPlugins() const +{ + QStringList plugins = {"SeventySix.esm"}; + + plugins.append(CCPlugins()); + + return plugins; +} + +QStringList GameFallout76::gameVariants() const +{ + return {"Regular"}; +} + +QString GameFallout76::gameShortName() const +{ + return "Fallout76"; +} + +QString GameFallout76::gameNexusName() const +{ + return "Fallout76"; +} + +QStringList GameFallout76::iniFiles() const +{ + return {"Fallout76.ini", "Fallout76Prefs.ini", "Fallout76Custom.ini"}; +} + +QStringList GameFallout76::DLCPlugins() const +{ + return {}; +} + +QStringList GameFallout76::CCPlugins() const +{ + QStringList plugins = {}; + QFile file(gameDirectory().absoluteFilePath("Fallout76.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 GameFallout76::sortMechanism() const +{ + return IPluginGame::SortMechanism::NONE; +} + +IPluginGame::LoadOrderMechanism GameFallout76::loadOrderMechanism() const +{ + return IPluginGame::LoadOrderMechanism::PluginsTxt; +} + +int GameFallout76::nexusModOrganizerID() const +{ + return -1; +} + +int GameFallout76::nexusGameID() const +{ + return 2590; +} -- cgit v1.3.1