diff options
| author | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-02-11 02:37:39 -0600 |
|---|---|---|
| committer | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-02-11 02:37:39 -0600 |
| commit | 7ee008e150bc5bcf76082d726f719ee0fdfda982 (patch) | |
| tree | 27fb39be241fdb5ac2734c574de678977d1856d0 /libs/game_bethesda/src/games/ttw | |
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/ttw')
15 files changed, 784 insertions, 0 deletions
diff --git a/libs/game_bethesda/src/games/ttw/CMakeLists.txt b/libs/game_bethesda/src/games/ttw/CMakeLists.txt new file mode 100644 index 0000000..27149ec --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.16) + +add_library(game_ttw SHARED + falloutttwbsainvalidation.cpp + falloutttwbsainvalidation.h + falloutttwdataarchives.cpp + falloutttwdataarchives.h + falloutttwmoddatachecker.h + falloutttwmoddatacontent.h + falloutttwsavegame.cpp + falloutttwsavegame.h + falloutttwscriptextender.cpp + falloutttwscriptextender.h + gamefalloutttw.cpp + gamefalloutttw.h +) +mo2_configure_plugin(game_ttw NO_SOURCES WARNINGS 4) +mo2_default_source_group() +target_link_libraries(game_ttw PRIVATE game_gamebryo) +mo2_install_plugin(game_ttw) diff --git a/libs/game_bethesda/src/games/ttw/falloutttwbsainvalidation.cpp b/libs/game_bethesda/src/games/ttw/falloutttwbsainvalidation.cpp new file mode 100644 index 0000000..67a7817 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/falloutttwbsainvalidation.cpp @@ -0,0 +1,16 @@ +#include "falloutttwbsainvalidation.h" + +FalloutTTWBSAInvalidation::FalloutTTWBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game) + : GamebryoBSAInvalidation(dataArchives, "fallout.ini", game) +{} + +QString FalloutTTWBSAInvalidation::invalidationBSAName() const +{ + return "Fallout - Invalidation.bsa"; +} + +unsigned long FalloutTTWBSAInvalidation::bsaVersion() const +{ + return 0x68; +} diff --git a/libs/game_bethesda/src/games/ttw/falloutttwbsainvalidation.h b/libs/game_bethesda/src/games/ttw/falloutttwbsainvalidation.h new file mode 100644 index 0000000..96062d3 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/falloutttwbsainvalidation.h @@ -0,0 +1,20 @@ +#ifndef FALLOUTTTWBSAINVALIDATION_H +#define FALLOUTTTWBSAINVALIDATION_H + +#include "falloutttwdataarchives.h" +#include "gamebryobsainvalidation.h" + +#include <memory> + +class FalloutTTWBSAInvalidation : public GamebryoBSAInvalidation +{ +public: + FalloutTTWBSAInvalidation(MOBase::DataArchives* dataArchives, + MOBase::IPluginGame const* game); + +private: + virtual QString invalidationBSAName() const override; + virtual unsigned long bsaVersion() const override; +}; + +#endif // FALLOUTTTWBSAINVALIDATION_H diff --git a/libs/game_bethesda/src/games/ttw/falloutttwdataarchives.cpp b/libs/game_bethesda/src/games/ttw/falloutttwdataarchives.cpp new file mode 100644 index 0000000..3ffb076 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/falloutttwdataarchives.cpp @@ -0,0 +1,31 @@ +#include "falloutttwdataarchives.h" +#include <utility.h> + +QStringList FalloutTTWDataArchives::vanillaArchives() const +{ + return {"Fallout - Textures.bsa", "Fallout - Textures2.bsa", "Fallout - Meshes.bsa", + "Fallout - Voices1.bsa", "Fallout - Sound.bsa", "Fallout - Misc.bsa"}; +} + +QStringList FalloutTTWDataArchives::archives(const MOBase::IProfile* profile) const +{ + QStringList result; + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") + : localGameDirectory().absoluteFilePath("fallout.ini"); + result.append(getArchivesFromKey(iniFile, "SArchiveList")); + + return result; +} + +void FalloutTTWDataArchives::writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) +{ + QString list = before.join(", "); + + QString iniFile = profile->localSettingsEnabled() + ? QDir(profile->absolutePath()).absoluteFilePath("fallout.ini") + : localGameDirectory().absoluteFilePath("fallout.ini"); + setArchivesToKey(iniFile, "SArchiveList", list); +} diff --git a/libs/game_bethesda/src/games/ttw/falloutttwdataarchives.h b/libs/game_bethesda/src/games/ttw/falloutttwdataarchives.h new file mode 100644 index 0000000..eb9d7c7 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/falloutttwdataarchives.h @@ -0,0 +1,23 @@ +#ifndef FALLOUTTTWDATAARCHIVES_H +#define FALLOUTTTWDATAARCHIVES_H + +#include <QDir> +#include <QString> +#include <QStringList> +#include <gamebryodataarchives.h> +#include <iprofile.h> + +class FalloutTTWDataArchives : public GamebryoDataArchives +{ +public: + using GamebryoDataArchives::GamebryoDataArchives; + + virtual QStringList vanillaArchives() const override; + virtual QStringList archives(const MOBase::IProfile* profile) const override; + +private: + virtual void writeArchiveList(MOBase::IProfile* profile, + const QStringList& before) override; +}; + +#endif // FALLOUTTTWDATAARCHIVES_H diff --git a/libs/game_bethesda/src/games/ttw/falloutttwmoddatachecker.h b/libs/game_bethesda/src/games/ttw/falloutttwmoddatachecker.h new file mode 100644 index 0000000..12ed881 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/falloutttwmoddatachecker.h @@ -0,0 +1,51 @@ +#ifndef FALLOUTTTW_MODATACHECKER_H +#define FALLOUTTTW_MODATACHECKER_H + +#include <gamebryomoddatachecker.h> + +class FalloutTTWModDataChecker : public GamebryoModDataChecker +{ +public: + using GamebryoModDataChecker::GamebryoModDataChecker; + +protected: + virtual const FileNameSet& possibleFolderNames() const override + { + static FileNameSet result{"fonts", + "interface", + "menus", + "meshes", + "music", + "scripts", + "shaders", + "sound", + "strings", + "textures", + "trees", + "video", + "facegen", + "materials", + "nvse", + "distantlod", + "asi", + "Tools", + "MCM", + "distantland", + "mits", + "dllplugins", + "CalienteTools", + "shadersfx", + "config", + "KEYWORDS", + "BaseObjectSwapper", + "RaceMenuPresets"}; + return result; + } + virtual const FileNameSet& possibleFileExtensions() const override + { + static FileNameSet result{"esp", "esm", "bsa", "modgroups", "ini"}; + return result; + } +}; + +#endif // FALLOUTTTW_MODATACHECKER_H diff --git a/libs/game_bethesda/src/games/ttw/falloutttwmoddatacontent.h b/libs/game_bethesda/src/games/ttw/falloutttwmoddatacontent.h new file mode 100644 index 0000000..37f9d20 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/falloutttwmoddatacontent.h @@ -0,0 +1,22 @@ +#ifndef FALLOUTTTW_MODDATACONTENT_H +#define FALLOUTTTW_MODDATACONTENT_H + +#include <gamebryomoddatacontent.h> +#include <ifiletree.h> + +class FalloutTTWModDataContent : public GamebryoModDataContent +{ +public: + /** + * + */ + FalloutTTWModDataContent(MOBase::IGameFeatures const* gameFeatures) + : GamebryoModDataContent(gameFeatures) + { + // Just need to disable some contents: + m_Enabled[CONTENT_MCM] = false; + m_Enabled[CONTENT_SKYPROC] = false; + } +}; + +#endif // FALLOUTTTW_MODDATACONTENT_H diff --git a/libs/game_bethesda/src/games/ttw/falloutttwsavegame.cpp b/libs/game_bethesda/src/games/ttw/falloutttwsavegame.cpp new file mode 100644 index 0000000..9f41082 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/falloutttwsavegame.cpp @@ -0,0 +1,79 @@ +#include "falloutttwsavegame.h" + +#include "gamefalloutttw.h" + +FalloutTTWSaveGame::FalloutTTWSaveGame(QString const& fileName, + GameFalloutTTW const* game) + : GamebryoSaveGame(fileName, game) +{ + FileWrapper file(getFilepath(), "FO3SAVEGAME"); + uint32_t width, height; + fetchInformationFields(file, width, height, m_SaveNumber, m_PCName, m_PCLevel, + m_PCLocation); +} + +void FalloutTTWSaveGame::fetchInformationFields(FileWrapper& file, uint32_t& width, + uint32_t& height, + uint32_t& saveNumber, + QString& playerName, + unsigned short& playerLevel, + QString& playerLocation) const +{ + file.skip<uint32_t>(); // Save header size + + file.skip<uint32_t>(); // File version? + file.skip<unsigned char>(); // Delimiter + + // A huge wodge of text with no length but a delimiter. Given the null bytes + // in it I presume it's fixed length (64 bytes + delim) but I have no + // definite spec + for (unsigned char ignore = 0; ignore != 0x7c;) { + file.read(ignore); // unknown + } + + file.setHasFieldMarkers(true); + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BZSTRING); + + file.read(width); + file.read(height); + file.read(saveNumber); + file.read(playerName); + + QString whatthis; + file.read(whatthis); + + long level; + file.read(level); + playerLevel = level; + file.read(playerLocation); +} + +std::unique_ptr<GamebryoSaveGame::DataFields> +FalloutTTWSaveGame::fetchDataFields() const +{ + FileWrapper file(getFilepath(), "FO3SAVEGAME"); + + std::unique_ptr<DataFields> fields = std::make_unique<DataFields>(); + + uint32_t width, height; + { + QString dummyName, dummyLocation; + unsigned short dummyLevel; + uint32_t dummySaveNumber; + + fetchInformationFields(file, width, height, dummySaveNumber, dummyName, dummyLevel, + dummyLocation); + } + + QString playtime; + file.read(playtime); + + fields->Screenshot = file.readImage(width, height, 256); + + file.skip<char>(5); // unknown (1 byte), plugin size (4 bytes) + + file.setPluginString(GamebryoSaveGame::StringType::TYPE_BSTRING); + fields->Plugins = file.readPlugins(); + + return fields; +} diff --git a/libs/game_bethesda/src/games/ttw/falloutttwsavegame.h b/libs/game_bethesda/src/games/ttw/falloutttwsavegame.h new file mode 100644 index 0000000..f8460b3 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/falloutttwsavegame.h @@ -0,0 +1,23 @@ +#ifndef FALLOUTTTWSAVEGAME_H +#define FALLOUTTTWSAVEGAME_H + +#include "gamebryosavegame.h" + +class GameFalloutTTW; + +class FalloutTTWSaveGame : public GamebryoSaveGame +{ +public: + FalloutTTWSaveGame(QString const& fileName, GameFalloutTTW const* game); + +protected: + // Fetch easy-to-access information. + void fetchInformationFields(FileWrapper& wrapper, uint32_t& width, + uint32_t& height, uint32_t& saveNumber, + QString& playerName, unsigned short& playerLevel, + QString& playerLocation) const; + + std::unique_ptr<DataFields> fetchDataFields() const override; +}; + +#endif // FALLOUTTTWSAVEGAME_H diff --git a/libs/game_bethesda/src/games/ttw/falloutttwscriptextender.cpp b/libs/game_bethesda/src/games/ttw/falloutttwscriptextender.cpp new file mode 100644 index 0000000..ab9474e --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/falloutttwscriptextender.cpp @@ -0,0 +1,18 @@ +#include "falloutttwscriptextender.h" + +#include <QString> +#include <QStringList> + +FalloutTTWScriptExtender::FalloutTTWScriptExtender(GameGamebryo const* game) + : GamebryoScriptExtender(game) +{} + +QString FalloutTTWScriptExtender::BinaryName() const +{ + return "nvse_loader.exe"; +} + +QString FalloutTTWScriptExtender::PluginPath() const +{ + return "nvse/plugins"; +} diff --git a/libs/game_bethesda/src/games/ttw/falloutttwscriptextender.h b/libs/game_bethesda/src/games/ttw/falloutttwscriptextender.h new file mode 100644 index 0000000..d1e4c9a --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/falloutttwscriptextender.h @@ -0,0 +1,17 @@ +#ifndef FALLOUTTTWSCRIPTEXTENDER_H +#define FALLOUTTTWSCRIPTEXTENDER_H + +#include "gamebryoscriptextender.h" + +class GameGamebryo; + +class FalloutTTWScriptExtender : public GamebryoScriptExtender +{ +public: + FalloutTTWScriptExtender(const GameGamebryo* game); + + virtual QString BinaryName() const override; + virtual QString PluginPath() const override; +}; + +#endif // FALLOUTTTWSCRIPTEXTENDER_H diff --git a/libs/game_bethesda/src/games/ttw/game_ttw_en.ts b/libs/game_bethesda/src/games/ttw/game_ttw_en.ts new file mode 100644 index 0000000..9d967f9 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/game_ttw_en.ts @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="en_US"> +<context> + <name>GameFalloutTTW</name> + <message> + <location filename="gamefalloutttw.cpp" line="185"/> + <source>Fallout TTW Support Plugin</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="gamefalloutttw.cpp" line="195"/> + <source>Adds support for the game Fallout TTW</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="gamefalloutttw.cpp" line="207"/> + <source>While not recommended by the TTW modding community, enables LOOT sorting</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/libs/game_bethesda/src/games/ttw/gamefalloutttw.cpp b/libs/game_bethesda/src/games/ttw/gamefalloutttw.cpp new file mode 100644 index 0000000..34eb1b2 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/gamefalloutttw.cpp @@ -0,0 +1,364 @@ +#include "gamefalloutttw.h" + +#include "falloutttwbsainvalidation.h" +#include "falloutttwdataarchives.h" +#include "falloutttwmoddatachecker.h" +#include "falloutttwmoddatacontent.h" +#include "falloutttwsavegame.h" +#include "falloutttwscriptextender.h" + +#include "executableinfo.h" +#include "pluginsetting.h" +#include "versioninfo.h" +#include <gamebryogameplugins.h> +#include <gamebryolocalsavegames.h> +#include <gamebryosavegameinfo.h> +#include <gamebryounmanagedmods.h> + +#include <QCoreApplication> +#include <QDir> +#include <QFileInfo> +#include <QList> +#include <QObject> +#include <QString> +#include <QStringList> + +#include <memory> + +using namespace MOBase; + +GameFalloutTTW::GameFalloutTTW() {} + +bool GameFalloutTTW::init(IOrganizer* moInfo) +{ + if (!GameGamebryo::init(moInfo)) { + return false; + } + + auto dataArchives = std::make_shared<FalloutTTWDataArchives>(this); + registerFeature(std::make_shared<FalloutTTWScriptExtender>(this)); + registerFeature(dataArchives); + registerFeature( + std::make_shared<FalloutTTWBSAInvalidation>(dataArchives.get(), this)); + registerFeature(std::make_shared<GamebryoSaveGameInfo>(this)); + registerFeature(std::make_shared<GamebryoLocalSavegames>(this, "fallout.ini")); + registerFeature(std::make_shared<FalloutTTWModDataChecker>(this)); + registerFeature( + std::make_shared<FalloutTTWModDataContent>(m_Organizer->gameFeatures())); + registerFeature(std::make_shared<GamebryoGamePlugins>(moInfo)); + registerFeature(std::make_shared<GamebryoUnmangedMods>(this)); + + return true; +} + +void GameFalloutTTW::setVariant(QString variant) +{ + m_GameVariant = variant; +} + +void GameFalloutTTW::checkVariants() +{ + QFileInfo gog_dll(m_GamePath + "\\Galaxy.dll"); + QFileInfo epic_dll(m_GamePath + "\\EOSSDK-Win32-Shipping.dll"); + if (gog_dll.exists()) + setVariant("GOG"); + else if (epic_dll.exists()) + setVariant("Epic Games"); + else + setVariant("Steam"); +} + +QDir GameFalloutTTW::documentsDirectory() const +{ + return m_MyGamesPath; +} + +QString GameFalloutTTW::identifyGamePath() const +{ + QString result; +#ifdef _WIN32 + QString path = "Software\\Bethesda Softworks\\FalloutNV"; + result = findInRegistry(HKEY_LOCAL_MACHINE, path.toStdWString().c_str(), + L"Installed Path"); +#else + result = GameGamebryo::identifyGamePath(); +#endif + // EPIC Game Store + if (result.isEmpty()) { + /** + * Basegame: 5daeb974a22a435988892319b3a4f476 + * Dead Money: b290229eb58045cbab9501640f3278f3 + * Honest Hearts: 562d4a2c1b3147b089a7c453e3ddbcbe + * Old World Blues: c8dae1ab0570475a8b38a9041e614840 + * Lonesome Road: 4fa3d8d9b2cb4714a19a38d1a598be8f + * Gun Runners' Arsenal: 7dcfb9cd9d134728b2646466c34c7b3b + * Courier's Stash: ee9a44b4530942499ef1c8c390731fce + */ + result = parseEpicGamesLocation({"5daeb974a22a435988892319b3a4f476"}); + if (QFileInfo(result).isDir()) { + QDir startPath = QDir(result); + auto subDirs = startPath.entryList({"Fallout New Vegas*"}, + QDir::Dirs | QDir::NoDotAndDotDot); + if (!subDirs.isEmpty()) + result += "/" + subDirs.first(); + } + } + return result; +} + +void GameFalloutTTW::setGamePath(const QString& path) +{ + m_GamePath = path; + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); +} + +QDir GameFalloutTTW::savesDirectory() const +{ + return QDir(m_MyGamesPath + "/Saves"); +} + +QString GameFalloutTTW::myGamesPath() const +{ + return m_MyGamesPath; +} + +bool GameFalloutTTW::isInstalled() const +{ + return !m_GamePath.isEmpty(); +} + +QString GameFalloutTTW::gameName() const +{ + return "TTW"; +} + +QString GameFalloutTTW::displayGameName() const +{ + return "Tale of Two Wastelands"; +} + +QString GameFalloutTTW::gameDirectoryName() const +{ + if (selectedVariant() == "Epic Games") + return "FalloutNV_Epic"; + else + return "FalloutNV"; +} + +void GameFalloutTTW::detectGame() +{ + m_GamePath = identifyGamePath(); + checkVariants(); + m_MyGamesPath = determineMyGamesPath(gameDirectoryName()); +} + +QList<ExecutableInfo> GameFalloutTTW::executables() const +{ + ExecutableInfo game("Tale of Two Wastelands", findInGameFolder(binaryName())); + ExecutableInfo launcher("Fallout Launcher", findInGameFolder(getLauncherName())); + QList<ExecutableInfo> extraExecutables = + QList<ExecutableInfo>() << ExecutableInfo("GECK", findInGameFolder("geck.exe")) + << ExecutableInfo("LOOT", QFileInfo(getLootPath())) + .withArgument("--game=\"FalloutNV\""); + if (selectedVariant() != "Epic Games") { + extraExecutables.prepend(ExecutableInfo( + "NVSE", findInGameFolder(m_Organizer->gameFeatures() + ->gameFeature<MOBase::ScriptExtender>() + ->loaderName()))); + } else { + game.withArgument("-EpicPortal"); + launcher.withArgument("-EpicPortal"); + } + QList<ExecutableInfo> executables = {game, launcher}; + executables += extraExecutables; + return executables; +} + +QList<ExecutableForcedLoadSetting> GameFalloutTTW::executableForcedLoads() const +{ + return QList<ExecutableForcedLoadSetting>(); +} + +QString GameFalloutTTW::name() const +{ + return "Fallout TTW Support Plugin"; +} + +QString GameFalloutTTW::localizedName() const +{ + return tr("Fallout TTW Support Plugin"); +} + +QString GameFalloutTTW::author() const +{ + return "SuperSandro2000 & MO2 Team"; +} + +QString GameFalloutTTW::description() const +{ + return tr("Adds support for the game Fallout TTW"); +} + +MOBase::VersionInfo GameFalloutTTW::version() const +{ + return VersionInfo(1, 6, 0, VersionInfo::RELEASE_FINAL); +} + +QList<PluginSetting> GameFalloutTTW::settings() const +{ + return QList<PluginSetting>() + << PluginSetting("enable_loot_sorting", + tr("While not recommended by the TTW modding community, " + "enables LOOT sorting"), + false); +} + +void GameFalloutTTW::initializeProfile(const QDir& path, ProfileSettings settings) const +{ + if (settings.testFlag(IPluginGame::MODS)) { + copyToProfile(localAppFolder() + "/" + gameDirectoryName(), path, "plugins.txt"); + } + + if (settings.testFlag(IPluginGame::CONFIGURATION)) { + if (settings.testFlag(IPluginGame::PREFER_DEFAULTS) || + !QFileInfo(myGamesPath() + "/fallout.ini").exists()) { + copyToProfile(gameDirectory().absolutePath(), path, "fallout_default.ini", + "fallout.ini"); + } else { + copyToProfile(myGamesPath(), path, "fallout.ini"); + } + + copyToProfile(myGamesPath(), path, "falloutprefs.ini"); + copyToProfile(myGamesPath(), path, "falloutcustom.ini"); + copyToProfile(myGamesPath(), path, "GECKCustom.ini"); + copyToProfile(myGamesPath(), path, "GECKPrefs.ini"); + } +} + +QString GameFalloutTTW::savegameExtension() const +{ + return "fos"; +} + +QString GameFalloutTTW::savegameSEExtension() const +{ + return "nvse"; +} + +std::shared_ptr<const GamebryoSaveGame> +GameFalloutTTW::makeSaveGame(QString filePath) const +{ + return std::make_shared<const FalloutTTWSaveGame>(filePath, this); +} + +QString GameFalloutTTW::steamAPPId() const +{ + if (selectedVariant() == "Steam") { + if (m_GamePath.endsWith("enplczru")) { + return "22490"; + } else { + return "22380"; + } + } + return QString(); +} + +QStringList GameFalloutTTW::primaryPlugins() const +{ + return {"falloutnv.esm", "deadmoney.esm", "honesthearts.esm", + "oldworldblues.esm", "lonesomeroad.esm", "gunrunnersarsenal.esm", + "fallout3.esm", "anchorage.esm", "thepitt.esm", + "brokensteel.esm", "pointlookout.esm", "zeta.esm", + "caravanpack.esm", "classicpack.esm", "mercenarypack.esm", + "tribalpack.esm", "taleoftwowastelands.esm", "YUPTTW.esm"}; +} + +QStringList GameFalloutTTW::gameVariants() const +{ + return {"Steam", "GOG", "Epic Games"}; +} + +QString GameFalloutTTW::binaryName() const +{ + return "FalloutNV.exe"; +} + +QString GameFalloutTTW::gameShortName() const +{ + return "TTW"; +} + +QStringList GameFalloutTTW::primarySources() const +{ + return {"FalloutNV"}; +} + +QStringList GameFalloutTTW::validShortNames() const +{ + return {"FalloutNV", "Fallout3"}; +} + +QString GameFalloutTTW::gameNexusName() const +{ + return ""; +} + +QStringList GameFalloutTTW::iniFiles() const +{ + return {"fallout.ini", "falloutprefs.ini", "falloutcustom.ini", "GECKCustom.ini", + "GECKPrefs.ini"}; +} + +QStringList GameFalloutTTW::DLCPlugins() const +{ + return {}; +} + +MOBase::IPluginGame::SortMechanism GameFalloutTTW::sortMechanism() const +{ + if (m_Organizer->pluginSetting(name(), "enable_loot_sorting").toBool()) + return IPluginGame::SortMechanism::LOOT; + return IPluginGame::SortMechanism::NONE; +} + +QString GameFalloutTTW::lootGameName() const +{ + return "FalloutNV"; +} + +int GameFalloutTTW::nexusModOrganizerID() const +{ + return 0; +} + +int GameFalloutTTW::nexusGameID() const +{ + return 0; +} + +QDir GameFalloutTTW::gameDirectory() const +{ + return QDir(m_GamePath); +} + +QString GameFalloutTTW::getLauncherName() const +{ + return "FalloutNVLauncher.exe"; +} + +MappingType GameFalloutTTW::mappings() const +{ + MappingType result; + + for (const QString& profileFile : {"plugins.txt", "loadorder.txt"}) { + result.push_back({m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/FalloutNV/" + profileFile, false}); + if (selectedVariant() == "Epic Games") { + result.push_back( + {m_Organizer->profilePath() + "/" + profileFile, + localAppFolder() + "/" + gameDirectoryName() + "/" + profileFile, false}); + } + } + return result; +} diff --git a/libs/game_bethesda/src/games/ttw/gamefalloutttw.h b/libs/game_bethesda/src/games/ttw/gamefalloutttw.h new file mode 100644 index 0000000..7f989b0 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/gamefalloutttw.h @@ -0,0 +1,77 @@ +#ifndef GAMEFALLOUTTTW_H +#define GAMEFALLOUTTTW_H + +#include "gamegamebryo.h" + +#include <QObject> +#include <QtGlobal> + +class GameFalloutTTW : public GameGamebryo +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + Q_PLUGIN_METADATA(IID "org.tannin.GameFalloutTTW" FILE "gamefalloutttw.json") +#endif + +public: + GameFalloutTTW(); + + bool init(MOBase::IOrganizer* moInfo) override; + +public: // IPluginGame interface + virtual QString gameName() const override; + virtual QString displayGameName() const override; + virtual void detectGame() override; + virtual QList<MOBase::ExecutableInfo> executables() const override; + virtual QList<MOBase::ExecutableForcedLoadSetting> + executableForcedLoads() const override; + virtual void initializeProfile(const QDir& path, + ProfileSettings settings) const override; + virtual QString steamAPPId() const override; + virtual QStringList primaryPlugins() const override; + virtual QStringList gameVariants() const override; + virtual QString binaryName() const override; + virtual QString gameShortName() const override; + virtual QStringList validShortNames() const override; + virtual QString gameNexusName() const override; + virtual QStringList iniFiles() const override; + virtual QStringList DLCPlugins() const override; + virtual int nexusModOrganizerID() const override; + virtual int nexusGameID() const override; + virtual QStringList primarySources() const override; + virtual SortMechanism sortMechanism() const override; + virtual QString lootGameName() const override; + virtual QString getLauncherName() const override; + + virtual bool isInstalled() const override; + virtual void setGamePath(const QString& path) override; + virtual QDir gameDirectory() const override; + +public: // IPlugin interface + virtual QString name() const override; + virtual QString localizedName() const override; + virtual QString author() const override; + virtual QString description() const override; + virtual MOBase::VersionInfo version() const override; + virtual QList<MOBase::PluginSetting> settings() const override; + +public: // IPluginFileMapper interface + virtual MappingType mappings() const override; + +protected: + QString gameDirectoryName() const; + QDir documentsDirectory() const; + QDir savesDirectory() const; + QString myGamesPath() const; + + void setVariant(QString variant); + void checkVariants(); + +protected: + virtual QString identifyGamePath() const override; + virtual QString savegameExtension() const override; + virtual QString savegameSEExtension() const override; + std::shared_ptr<const GamebryoSaveGame> makeSaveGame(QString filePath) const override; +}; + +#endif // GAMEFALLOUTTTW_H diff --git a/libs/game_bethesda/src/games/ttw/gamefalloutttw.json b/libs/game_bethesda/src/games/ttw/gamefalloutttw.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/libs/game_bethesda/src/games/ttw/gamefalloutttw.json @@ -0,0 +1 @@ +{} |
